成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

從構建分布式秒殺系統聊聊限流特技

存儲 存儲軟件 分布式
俗話說的好,冰凍三尺非一日之寒,滴水穿石非一日之功,羅馬也不是一天就建成的。兩周前秒殺案例初步成型,分享到了中國最大的同×××友網站-碼云。同時也收到了不少小伙伴的建議和投訴。我從不認為分布式、集群、秒殺這些就應該是大廠的專利,在互聯網的今天無論什么時候都要時刻武裝自己,只有這樣,也許你的春天就在明天。

前言

俗話說的好,冰凍三尺非一日之寒,滴水穿石非一日之功,羅馬也不是一天就建成的。兩周前秒殺案例初步成型,分享到了中國***的同×××友網站-碼云。同時也收到了不少小伙伴的建議和投訴。我從不認為分布式、集群、秒殺這些就應該是大廠的專利,在互聯網的今天無論什么時候都要時刻武裝自己,只有這樣,也許你的春天就在明天。

在開發秒殺系統案例的過程中,前面主要分享了隊列、緩存、鎖和分布式鎖以及靜態化等等。緩存的目的是為了提升系統訪問速度和增強系統的處理能力;分布式鎖解決了集群下數據的安全一致性問題;靜態化無疑是減輕了緩存以及DB層的壓力。

[[233265]]

限流

然而再牛逼的機器,再優化的設計,對于特殊場景我們也是要特殊處理的。就拿秒殺來說,可能會有***別的用戶進行搶購,而商品數量遠遠小于用戶數量。如果這些請求都進入隊列或者查詢緩存,對于最終結果沒有任何意義,徒增后臺華麗的數據。對此,為了減少資源浪費,減輕后端壓力,我們還需要對秒殺進行限流,只需保障部分用戶服務正常即可。

就秒殺接口來說,當訪問頻率或者并發請求超過其承受范圍的時候,這時候我們就要考慮限流來保證接口的可用性,以防止非預期的請求對系統壓力過大而引起的系統癱瘓。通常的策略就是拒絕多余的訪問,或者讓多余的訪問排隊等待服務。

限流算法

任何限流都不是漫無目的的,也不是一個開關就可以解決的問題,常用的限流算法有:令牌桶,漏桶。

令牌桶

令牌桶算法是網絡流量×××(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的一種算法。典型情況下,令牌桶算法用來控制發送到網絡上的數據的數目,并允許突發數據的發送(百科)。

在秒殺活動中,用戶的請求速率是不固定的,這里我們假定為10r/s,令牌按照5個每秒的速率放入令牌桶,桶中最多存放20個令牌。仔細想想,是不是總有那么一部分請求被丟棄。

漏桶

漏桶算法的主要目的是控制數據注入到網絡的速率,平滑網絡上的突發流量。漏桶算法提供了一種機制,通過它,突發流量可以被×××以便為網絡提供一個穩定的流量(百科)。

令牌桶是無論你流入速率多大,我都按照既定的速率去處理,如果桶滿則拒絕服務。

應用限流

Tomcat

在Tomcat容器中,我們可以通過自定義線程池,配置***連接數,請求處理隊列等參數來達到限流的目的(圖片源自網絡)。

Tomcat默認使用自帶的連接池,這里我們也可以自定義實現,打開/conf/server.xml文件,在Connector之前配置一個線程池:

  1. <Executor name="tomcatThreadPool" 
  2.         namePrefix="tomcatThreadPool-" 
  3.         maxThreads="1000" 
  4.         maxIdleTime="300000" 
  5.         minSpareThreads="200"/> 
  • name:共享線程池的名字。這是Connector為了共享線程池要引用的名字,該名字必須唯一。默認值:None;
  • namePrefix:在JVM上,每個運行線程都可以有一個name 字符串。這一屬性為線程池中每個線程的name字符串設置了一個前綴,Tomcat將把線程號追加到這一前綴的后面。默認值:tomcat-exec-;
  • maxThreads:該線程池可以容納的***線程數。默認值:200;
  • maxIdleTime:在Tomcat關閉一個空閑線程之前,允許空閑線程持續的時間(以毫秒為單位)。只有當前活躍的線程數大于minSpareThread的值,才會關閉空閑線程。默認值:60000(一分鐘)。
  • minSpareThreads:Tomcat應該始終打開的最小不活躍線程數。默認值:25。

配置Connector

  1. <Connector executor="tomcatThreadPool" 
  2.            port="8080" protocol="HTTP/1.1" 
  3.            connectionTimeout="20000" 
  4.            redirectPort="8443" 
  5.            minProcessors="5" 
  6.            maxProcessors="75" 
  7.            acceptCount="1000"/> 
  • executor:表示使用該參數值對應的線程池;
  • minProcessors:服務器啟動時創建的處理請求的線程數;
  • maxProcessors:***可以創建的處理請求的線程數;
  • acceptCount:指定當所有可以使用的處理請求的線程數都被使用時,可以放到處理隊列中的請求數,超過這個數的請求將不予處理。

API限流

秒殺活動中,接口的請求量會是平時的數百倍甚至數千倍,從而有可能導致接口不可用,并引發連鎖反應導致整個系統崩潰,甚至有可能會影響到其它服務。

那么如何應對這種突然事件呢?這里我們采用開源工具包guava提供的限流工具類RateLimiter進行API限流,該類基于"令牌桶算法",開箱即用。

  1. /** 
  2.  * 自定義注解  限流 
  3.  */ 
  4. @Target({ElementType.PARAMETER, ElementType.METHOD}) 
  5. @Retention(RetentionPolicy.RUNTIME) 
  6. @Documented 
  7. public  @interface ServiceLimit { 
  8.      String description()  default ""

自定義切面

  1. /** 
  2.  * 限流 AOP 
  3.  */ 
  4. @Component 
  5. @Scope 
  6. @Aspect 
  7. public class LimitAspect { 
  8.     //每秒只發出100個令牌,此處是單進程服務的限流,內部采用令牌捅算法實現 
  9.     private static   RateLimiter rateLimiter = RateLimiter.create(100.0); 
  10.  
  11.     //Service層切點  限流 
  12.     @Pointcut("@annotation(com.itstyle.seckill.common.aop.ServiceLimit)")   
  13.     public void ServiceAspect() { 
  14.  
  15.     } 
  16.  
  17.     @Around("ServiceAspect()"
  18.     public  Object around(ProceedingJoinPoint joinPoint) {  
  19.         Boolean flag = rateLimiter.tryAcquire(); 
  20.         Object obj = null
  21.         try { 
  22.             if(flag){ 
  23.                 obj = joinPoint.proceed(); 
  24.             } 
  25.         } catch (Throwable e) { 
  26.             e.printStackTrace(); 
  27.         } 
  28.         return obj; 
  29.     } 

業務實現:

  1. @Override 
  2. @ServiceLimit 
  3. @Transactional 
  4. public Result startSeckil(long seckillId, long userId) { 
  5.     //省略部分業務代碼,詳見秒殺源碼 

分布式限流

Nginx

  1. #統一在http域中進行配置 
  2. #限制請求 
  3. limit_req_zone $binary_remote_addr $uri zone=api_read:20m rate=50r/s; 
  4. #按ip配置一個連接 zone 
  5. limit_conn_zone $binary_remote_addr zone=perip_conn:10m; 
  6. #按server配置一個連接 zone 
  7. limit_conn_zone $server_name zone=perserver_conn:100m; 
  8. server { 
  9.         listen       80; 
  10.         server_name  seckill.52itstyle.com; 
  11.         index index.jsp; 
  12.         location / { 
  13.               #請求限流排隊通過 burst默認是0 
  14.               limit_req zone=api_read burst=5; 
  15.               #連接數限制,每個IP并發請求為2 
  16.               limit_conn perip_conn 2; 
  17.               #服務所限制的連接數(即限制了該server并發連接數量) 
  18.               limit_conn perserver_conn 1000; 
  19.               #連接限速 
  20.               limit_rate 100k; 
  21.               proxy_pass      http://seckill; 
  22.         } 
  23. upstream seckill { 
  24.         fair; 
  25.         server  172.16.1.120:8080 weight=1  max_fails=2 fail_timeout=30s; 
  26.         server  172.16.1.130:8080 weight=1  max_fails=2 fail_timeout=30s; 

配置說明

  1. imit_conn_zone 

是針對每個IP定義一個存儲session狀態的容器。這個示例中定義了一個100m的容器,按照32bytes/session,可以處理3200000個session。

  1. limit_rate 300k; 

對每個連接限速300k. 注意,這里是對連接限速,而不是對IP限速。如果一個IP允許兩個并發連接,那么這個IP就是限速limit_rate×2。

  1. burst=5; 

這相當于桶的大小,如果某個請求超過了系統處理速度,會被放入桶中,等待被處理。如果桶滿了,那么抱歉,請求直接返回503,客戶端得到一個服務器忙的響應。如果系統處理請求的速度比較慢,桶里的請求也不能一直待在里面,如果超過一定時間,也是會被直接退回,返回服務器忙的響應。

OpenResty

背影有沒有很熟悉,對這就是那個直呼理解萬歲老羅,2015年老羅在錘子科技T2發布會上將門票收入捐贈給了 OpenResty,也相信老羅是個有情懷的胖子。

這里我們使用 OpenResty 開源的限流方案,測試案例使用OpenResty1.13.6.1***版本,自帶lua-resty-limit-traffic模塊以及案例 ,實現起來更為方便。

限制接口總并發數/請求數

秒殺活動中,由于突發流量暴增,有可能會影響整個系統的穩定性從而造成崩潰,這時候我們就要限制秒殺接口的總并發數/請求數。

這里我們采用 lua-resty-limit-traffic中的resty.limit.count模塊實現,由于文章篇幅具體代碼參見源碼openresty/lua/limit_count.lua。

限制接口時間窗請求數

秒殺場景下,有時候并都是人肉鼠標,比如12306的搶票軟件,軟件刷票可比人肉鼠標快多了。此時我們就要對客戶端單位時間內的請求數進行限制,以至于刷票不是那么猖獗。當然了道高一尺魔高一丈,搶票軟件總是會有辦法繞開你的防線,從另一方面講也促進了技術的進步。

這里我們采用 lua-resty-limit-traffic中的resty.limit.conn模塊實現,具體代碼參見源碼openresty/lua/limit_conn.lua。

平滑限制接口請求數

之前的限流方式允許突發流量,也就是說瞬時流量都會被允許。突然流量如果不加以限制會影響整個系統的穩定性,因此在秒殺場景中需要對請求×××為平均速率處理,即20r/s。

這里我們采用 lua-resty-limit-traffic 中的resty.limit.req 模塊實現漏桶限流和令牌桶限流。

其實漏桶和令牌桶根本的區別就是,如何處理超過請求速率的請求。漏桶會把請求放入隊列中去等待均速處理,隊列滿則拒絕服務;令牌桶在桶容量允許的情況下直接處理這些突發請求。

漏桶

桶容量大于零,并且是延遲模式。如果桶沒滿,則進入請求隊列以固定速率等待處理,否則請求被拒絕。

令牌桶

桶容量大于零,并且是非延遲模式。如果桶中存在令牌,則允許突發流量,否則請求被拒絕。

壓測

為了測試以上配置效果,我們采用AB壓測,Linux下執行以下命令即可:

  1. # 安裝 
  2. yum -y install httpd-tools 
  3. # 查看ab版本 
  4. ab -v 
  5. # 查看幫助 
  6. ab --help 

測試命令:

  1. ab -n 1000 -c 100 http://127.0.0.1/ 

測試結果:

  1. Server Software:        openresty/1.13.6.1  #服務器軟件 
  2. Server Hostname:        127.0.0.1     #IP 
  3. Server Port:            80            #請求端口號 
  4.  
  5. Document Path:          /             #文件路徑 
  6. Document Length:        12 bytes      #頁面字節數 
  7.  
  8. Concurrency Level:      100           #請求的并發數 
  9. Time taken for tests:   4.999 seconds #總訪問時間 
  10. Complete requests:      1000          #總請求樹 
  11. Failed requests:        0             #請求失敗數量 
  12. Write errors:           0 
  13. Total transferred:      140000 bytes  #請求總數據大小 
  14. HTML transferred:       12000 bytes   #html頁面實際總字節數 
  15. Requests per second:    200.06 [#/sec] (mean) #每秒多少請求,這個是非常重要的參數數值,服務器的吞吐量 
  16. Time per request:       499.857 [ms] (mean) #用戶平均請求等待時間  
  17. Time per request:       4.999 [ms] (mean, across all concurrent requests)  # 服務器平均處理時間,也就是服務器吞吐量的倒數  
  18. Transfer rate:          27.35 [Kbytes/sec] received #每秒獲取的數據長度 
  19.  
  20. Connection Times (ms) 
  21.               min  mean[+/-sd] median   max 
  22. Connect:        0    0   0.8      0       4 
  23. Processing:     5  474  89.1    500     501 
  24. Waiting:        2  474  89.2    500     501 
  25. Total:          9  475  88.4    500     501 
  26.  
  27. Percentage of the requests served within a certain time (ms) 
  28.   50%    500 
  29.   66%    500 
  30.   75%    500 
  31.   80%    500 
  32.   90%    501 
  33.   95%    501 
  34.   98%    501 
  35.   99%    501 
  36.  100%    501 (longest request) 

總結

以上限流方案,只是針對此次秒殺案例做一個簡單的小結,大家也不要刻意區分那種方案的好壞,只要適合業務場景就是***的。

參考

https://github.com/openresty/lua-resty-limit-traffic

https://blog.52itstyle.com/archives/1764/

https://blog.52itstyle.com/archives/775/

分享是快樂的,也見證了個人成長歷程,文章大多都是工作經驗總結以及平時學習積累,基于自身認知不足之處在所難免,也請大家指正,共同進步。

本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出, 如有問題, 可郵件(345849402@qq.com)咨詢。

責任編輯:武曉燕 來源: 51CTO博客
相關推薦

2018-06-11 11:12:09

秒殺限流分布式

2018-07-19 14:53:23

秒殺websocket異步

2016-11-28 08:58:43

系統限流

2016-11-28 08:58:43

系統限流算法

2023-02-10 00:04:53

2017-12-20 16:15:30

分布式系統架構

2024-07-05 08:26:54

2018-01-23 15:55:23

分布式系統架構

2017-09-01 05:35:58

分布式計算存儲

2025-03-06 11:30:15

2022-06-13 10:01:36

Apollo攜程框架

2022-05-11 13:55:18

高可用性分布式彈性

2023-01-06 16:42:28

2023-04-06 08:52:54

Sentinel分布式系統

2022-01-17 09:18:28

JMeter分布式壓測

2016-11-28 08:40:17

系統降級服務

2023-05-29 14:07:00

Zuul網關系統

2022-03-07 08:14:27

并發分布式

2021-02-01 09:35:53

關系型數據庫模型

2018-04-03 09:27:42

分布式架構系統
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品精品视频一区二区三区 | 欧美日韩国产精品激情在线播放 | 国产欧美精品一区二区色综合朱莉 | 日本成人中文字幕在线观看 | 精品人伦一区二区三区蜜桃网站 | 中文字幕 欧美 日韩 | 国产精品一区在线观看你懂的 | 在线观看日本高清二区 | 天天天天天天天干 | 久久99国产精一区二区三区 | 欧美一区二区三区一在线观看 | 亚洲视频手机在线 | 国产成人精品免高潮在线观看 | 日本福利一区 | 日本精品裸体写真集在线观看 | 久久久久无码国产精品一区 | 日韩一区二区三区四区五区 | 一区二区三区欧美在线 | 国产成人福利在线观看 | 男女羞羞视频在线观看 | 亚洲精品乱码久久久久久蜜桃 | 久久亚洲欧美日韩精品专区 | 免费在线观看一区二区三区 | 日韩黄 | 日韩欧美在线精品 | 天天操夜夜操免费视频 | 日本久久精品视频 | 欧美日韩综合精品 | 91麻豆精品国产91久久久久久久久 | 91n成人 | 男人影音 | 色爱综合 | 性高朝久久久久久久3小时 av一区二区三区四区 | 久久视频一区 | 亚洲永久精品国产 | 亚洲欧美一区二区三区1000 | 国产精品国产三级国产播12软件 | 99精品国产一区二区三区 | 国产精品一区在线 | 精品欧美乱码久久久久久1区2区 | 区一区二在线观看 |