新聞中心
上一篇《聊聊高并發(fā)系統(tǒng)限流特技-1》講了限流算法、應(yīng)用級限流、分布式限流;本篇將介紹接入層限流實(shí)現(xiàn)。

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名與空間、雅安服務(wù)器托管、營銷軟件、網(wǎng)站建設(shè)、瀾滄網(wǎng)站維護(hù)、網(wǎng)站推廣。
接入層限流
接入層通常指請求流量的入口,該層的主要目的有:負(fù)載均衡、非法請求過濾、請求聚合、緩存、降級、限流、A/B測試、服務(wù)質(zhì)量監(jiān)控等等,可以參考筆者寫的《使用Nginx+Lua(OpenResty)開發(fā)高性能Web應(yīng)用》。
對于Nginx接入層限流可以使用Nginx自帶了兩個(gè)模塊:連接數(shù)限流模塊ngx_http_limit_conn_module和漏桶算法實(shí)現(xiàn)的請求限流模塊ngx_http_limit_req_module。還可以使用OpenResty提供的Lua限流模塊lua-resty-limit-traffic進(jìn)行更復(fù)雜的限流場景。
limit_conn用來對某個(gè)KEY對應(yīng)的總的網(wǎng)絡(luò)連接數(shù)進(jìn)行限流,可以按照如IP、域名維度進(jìn)行限流。limit_req用來對某個(gè)KEY對應(yīng)的請求的平均速率進(jìn)行限流,并有兩種用法:平滑模式(delay)和允許突發(fā)模式(nodelay)。
ngx_http_limit_conn_module
limit_conn是對某個(gè)KEY對應(yīng)的總的網(wǎng)絡(luò)連接數(shù)進(jìn)行限流??梢园凑誌P來限制IP維度的總連接數(shù),或者按照服務(wù)域名來限制某個(gè)域名的總連接數(shù)。但是記住不是每一個(gè)請求連接都會被計(jì)數(shù)器統(tǒng)計(jì),只有那些被Nginx處理的且已經(jīng)讀取了整個(gè)請求頭的請求連接才會被計(jì)數(shù)器統(tǒng)計(jì)。
配置示例:
- http {
- limit_conn_zone$binary_remote_addr zone=addr:10m;
- limit_conn_log_level error;
- limit_conn_status 503;
- ...
- server {
- ...
- location /limit {
- limit_conn addr 1;
- }
limit_conn:要配置存放KEY和計(jì)數(shù)器的共享內(nèi)存區(qū)域和指定KEY的最大連接數(shù);此處指定的最大連接數(shù)是1,表示Nginx最多同時(shí)并發(fā)處理1個(gè)連接;
limit_conn_zone:用來配置限流KEY、及存放KEY對應(yīng)信息的共享內(nèi)存區(qū)域大小;此處的KEY是“$binary_remote_addr”其表示IP地址,也可以使用如$server_name作為KEY來限制域名級別的最大連接數(shù);
limit_conn_status:配置被限流后返回的狀態(tài)碼,默認(rèn)返回503;
limit_conn_log_level:配置記錄被限流后的日志級別,默認(rèn)error級別。
limit_conn的主要執(zhí)行過程如下所示:
1、請求進(jìn)入后首先判斷當(dāng)前l(fā)imit_conn_zone中相應(yīng)KEY的連接數(shù)是否超出了配置的最大連接數(shù);
2.1、如果超過了配置的最大大小,則被限流,返回limit_conn_status定義的錯(cuò)誤狀態(tài)碼;
2.2、否則相應(yīng)KEY的連接數(shù)加1,并注冊請求處理完成的回調(diào)函數(shù);
3、進(jìn)行請求處理;
4、在結(jié)束請求階段會調(diào)用注冊的回調(diào)函數(shù)對相應(yīng)KEY的連接數(shù)減1。
limt_conn可以限流某個(gè)KEY的總并發(fā)/請求數(shù),KEY可以根據(jù)需要變化。
按照IP限制并發(fā)連接數(shù)配置示例:
首先定義IP維度的限流區(qū)域:
- limit_conn_zone $binary_remote_addrzone=perip:10m;
接著在要限流的location中添加限流邏輯:
- location /limit {
- limit_conn perip 2;
- echo "123";
- }
即允許每個(gè)IP最大并發(fā)連接數(shù)為2。
使用AB測試工具進(jìn)行測試,并發(fā)數(shù)為5個(gè),總的請求數(shù)為5個(gè):
- ab -n 5 -c 5 http://localhost/limit
將得到如下access.log輸出:
[08/Jun/2016:20:10:51+0800] [1465373451.802] 200
[08/Jun/2016:20:10:51+0800] [1465373451.803] 200
[08/Jun/2016:20:10:51 +0800][1465373451.803] 503
[08/Jun/2016:20:10:51 +0800][1465373451.803] 503
[08/Jun/2016:20:10:51 +0800][1465373451.803] 503
此處我們把a(bǔ)ccess log格式設(shè)置為log_format main '[$time_local] [$msec] $status';分別是“日期 日期秒/毫秒值 響應(yīng)狀態(tài)碼”。
如果被限流了,則在error.log中會看到類似如下的內(nèi)容:
- 2016/06/08 20:10:51 [error] 5662#0: *5limiting connections by zone "perip", client: 127.0.0.1, server: _,request: "GET /limit HTTP/1.0", host: "localhost"
按照域名限制并發(fā)連接數(shù)配置示例:
首先定義域名維度的限流區(qū)域:
- limit_conn_zone $ server_name zone=perserver:10m;
接著在要限流的location中添加限流邏輯:
- location /limit {
- limit_conn perserver 2;
- echo "123";
- }
即允許每個(gè)域名最大并發(fā)請求連接數(shù)為2;這樣配置可以實(shí)現(xiàn)服務(wù)器最大連接數(shù)限制。
ngx_http_limit_req_module
limit_req是令牌桶算法實(shí)現(xiàn),用于對指定KEY對應(yīng)的請求進(jìn)行限流,比如按照IP維度限制請求速率。
配置示例:
- http {
- limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
- limit_conn_log_level error;
- limit_conn_status 503;
- ...
- server {
- ...
- location /limit {
- limit_req zone=one burst=5 nodelay;
- }
limit_req:配置限流區(qū)域、桶容量(突發(fā)容量,默認(rèn)0)、是否延遲模式(默認(rèn)延遲);
limit_req_zone:配置限流KEY、及存放KEY對應(yīng)信息的共享內(nèi)存區(qū)域大小、固定請求速率;此處指定的KEY是“$binary_remote_addr”表示IP地址;固定請求速率使用rate參數(shù)配置,支持10r/s和60r/m,即每秒10個(gè)請求和每分鐘60個(gè)請求,不過最終都會轉(zhuǎn)換為每秒的固定請求速率(10r/s為每100毫秒處理一個(gè)請求;60r/m,即每1000毫秒處理一個(gè)請求)。
limit_conn_status:配置被限流后返回的狀態(tài)碼,默認(rèn)返回503;
limit_conn_log_level:配置記錄被限流后的日志級別,默認(rèn)error級別。
limit_req的主要執(zhí)行過程如下所示:
1、請求進(jìn)入后首先判斷最后一次請求時(shí)間相對于當(dāng)前時(shí)間(第一次是0)是否需要限流,如果需要限流則執(zhí)行步驟2,否則執(zhí)行步驟3;
2.1、如果沒有配置桶容量(burst),則桶容量為0;按照固定速率處理請求;如果請求被限流,則直接返回相應(yīng)的錯(cuò)誤碼(默認(rèn)503);
2.2、如果配置了桶容量(burst>0)且延遲模式(沒有配置nodelay);如果桶滿了,則新進(jìn)入的請求被限流;如果沒有滿則請求會以固定平均速率被處理(按照固定速率并根據(jù)需要延遲處理請求,延遲使用休眠實(shí)現(xiàn));
2.3、如果配置了桶容量(burst>0)且非延遲模式(配置了nodelay);不會按照固定速率處理請求,而是允許突發(fā)處理請求;如果桶滿了,則請求被限流,直接返回相應(yīng)的錯(cuò)誤碼;
3、如果沒有被限流,則正常處理請求;
4、Nginx會在相應(yīng)時(shí)機(jī)進(jìn)行選擇一些(3個(gè)節(jié)點(diǎn))限流KEY進(jìn)行過期處理,進(jìn)行內(nèi)存回收。
場景2.1測試
首先定義IP維度的限流區(qū)域:
- limit_req_zone $binary_remote_addrzone=test:10m rate=500r/s;
限制為每秒500個(gè)請求,固定平均速率為2毫秒一個(gè)請求。
接著在要限流的location中添加限流邏輯:
- location /limit {
- limit_req zone=test;
- echo "123";
- }
即桶容量為0(burst默認(rèn)為0),且延遲模式。
使用AB測試工具進(jìn)行測試,并發(fā)數(shù)為2個(gè),總的請求數(shù)為10個(gè):
- ab -n 10 -c 2 http://localhost/limit
將得到如下access.log輸出:
[08/Jun/2016:20:25:56+0800] [1465381556.410] 200
[08/Jun/2016:20:25:56 +0800][1465381556.410] 503
[08/Jun/2016:20:25:56 +0800][1465381556.411] 503
[08/Jun/2016:20:25:56+0800] [1465381556.411] 200
[08/Jun/2016:20:25:56 +0800][1465381556.412] 503
[08/Jun/2016:20:25:56 +0800][1465381556.412] 503
雖然每秒允許500個(gè)請求,但是因?yàn)橥叭萘繛?,所以流入的請求要么被處理要么被限流,無法延遲處理;另外平均速率在2毫秒左右,比如1465381556.410和1465381556.411被處理了;有朋友會說這固定平均速率不是1毫秒嘛,其實(shí)這是因?yàn)閷?shí)現(xiàn)算法沒那么精準(zhǔn)造成的。
如果被限流在error.log中會看到如下內(nèi)容:
- 2016/06/08 20:25:56 [error] 6130#0: *1962limiting requests, excess: 1.000 by zone "test", client: 127.0.0.1,server: _, request: "GET /limit HTTP/1.0", host:"localhost"
如果被延遲了在error.log(日志級別要INFO級別)中會看到如下內(nèi)容:
- 2016/06/10 09:05:23 [warn] 9766#0: *97021delaying request, excess: 0.368, by zone "test", client: 127.0.0.1,server: _, request: "GET /limit HTTP/1.0", host:"localhost"
場景2.2測試
首先定義IP維度的限流區(qū)域:
- limit_req_zone $binary_remote_addr zone=test:10m rate=2r/s;
為了方便測試設(shè)置速率為每秒2個(gè)請求,即固定平均速率是500毫秒一個(gè)請求。
接著在要限流的location中添加限流邏輯:
- location /limit {
- limit_req zone=test burst=3;
- echo "123";
- }
固定平均速率為500毫秒一個(gè)請求,通容量為3,如果桶滿了新的請求被限流,否則可以進(jìn)入桶中排隊(duì)并等待(實(shí)現(xiàn)延遲模式)。
為了看出限流效果我們寫了一個(gè)req.sh腳本:
- ab -c 6 -n 6 http://localhost/limit
- sleep 0.3
- ab -c 6 -n 6 http://localhost/limit
首先進(jìn)行6個(gè)并發(fā)請求6次URL,然后休眠300毫秒,然后再進(jìn)行6個(gè)并發(fā)請求6次URL;中間休眠目的是為了能跨越2秒看到效果,如果看不到如下的效果可以調(diào)節(jié)休眠時(shí)間。
將得到如下access.log輸出:
[09/Jun/2016:08:46:43+0800] [1465433203.959] 200
[09/Jun/2016:08:46:43 +0800][1465433203.959] 503
[09/Jun/2016:08:46:43 +0800][1465433203.960] 503
[09/Jun/2016:08:46:44+0800] [1465433204.450] 200
[09/Jun/2016:08:46:44+0800] [1465433204.950] 200
[09/Jun/2016:08:46:45 +0800][1465433205.453] 200
[09/Jun/2016:08:46:45 +0800][1465433205.766] 503
[09/Jun/2016:08:46:45 +0800][1465433205.766] 503
[09/Jun/2016:08:46:45 +0800][1465433205.767] 503
[09/Jun/2016:08:46:45+0800] [1465433205.950] 200
[09/Jun/2016:08:46:46+0800] [1465433206.451] 200
[09/Jun/2016:08:46:46+0800] [1465433206.952] 200
桶容量為3,即桶中在時(shí)間窗口內(nèi)最多流入3個(gè)請求,且按照2r/s的固定速率處理請求(即每隔500毫秒處理一個(gè)請求);桶計(jì)算時(shí)間窗口(1.5秒)=速率(2r/s)/桶容量(3),也就是說在這個(gè)時(shí)間窗口內(nèi)桶最多暫存3個(gè)請求。因此我們要以當(dāng)前時(shí)間往前推1.5秒和1秒來計(jì)算時(shí)間窗口內(nèi)的總請求數(shù);另外因?yàn)槟J(rèn)是延遲模式,所以時(shí)間窗內(nèi)的請求要被暫存到桶中,并以固定平均速率處理請求:
第一輪:有4個(gè)請求處理成功了,按照漏桶桶容量應(yīng)該最多3個(gè)才對;這是因?yàn)橛?jì)算算法的問題,第一次計(jì)算因沒有參考值,所以第一次計(jì)算后,后續(xù)的計(jì)算才能有參考值,因此第一次成功可以忽略;這個(gè)問題影響很小可以忽略;而且按照固定500毫秒的速率處理請求。
第二輪:因?yàn)榈谝惠喺埱笫峭话l(fā)來的,差不多都在1465433203.959時(shí)間點(diǎn),只是因?yàn)槁┩皩⑺俾蔬M(jìn)行了平滑變成了固定平均速率(每500毫秒一個(gè)請求);而第二輪計(jì)算時(shí)間應(yīng)基于1465433203.959;而第二輪突發(fā)請求差不多都在1465433205.766時(shí)間點(diǎn),因此計(jì)算桶容量的時(shí)間窗口應(yīng)基于1465433203.959和1465433205.766來計(jì)算,計(jì)算結(jié)果為1465433205.766這個(gè)時(shí)間點(diǎn)漏桶為空了,可以流入桶中3個(gè)請求,其他請求被拒絕;又因?yàn)榈谝惠喿詈笠淮翁幚頃r(shí)間是1465433205.453,所以第二輪第一個(gè)請求被延遲到了1465433205.950。這里也要注意固定平均速率只是在配置的速率左右,存在計(jì)算精度問題,會有一些偏差。
如果桶容量改為1(burst=1),執(zhí)行req.sh腳本可以看到如下輸出:
[09/Jun/2016:09:04:30+0800] [1465434270.362] 200
[09/Jun/2016:09:04:30 +0800][1465434270.371] 503
[09/Jun/2016:09:04:30 +0800] [1465434270.372]503
[09/Jun/2016:09:04:30 +0800][1465434270.372] 503
[09/Jun/2016:09:04:30 +0800][1465434270.372] 503
[09/Jun/2016:09:04:30+0800] [1465434270.864] 200
[09/Jun/2016:09:04:31 +0800][1465434271.178] 503
[09/Jun/2016:09:04:31 +0800][1465434271.178] 503
[09/Jun/2016:09:04:31 +0800][1465434271.178] 503
[09/Jun/2016:09:04:31 +0800][1465434271.178] 503
[09/Jun/2016:09:04:31 +0800][1465434271.179] 503
[09/Jun/2016:09:04:31+0800] [1465434271.366] 200
桶容量為1,按照每1000毫秒一個(gè)請求的固定平均速率處理請求。
場景2.3測試
首先定義IP維度的限流區(qū)域:
- limit_req_zone $binary_remote_addrzone=test:10m rate=2r/s;
為了方便測試配置為每秒2個(gè)請求,固定平均速率是500毫秒一個(gè)請求。
接著在要限流的location中添加限流邏輯:
- location /limit {
- limit_req zone=test burst=3 nodelay;
- echo "123";
- }
桶容量為3,如果桶滿了直接拒絕新請求,且每秒2最多兩個(gè)請求,桶按照固定500毫秒的速率以nodelay模式處理請求。
為了看到限流效果我們寫了一個(gè)req.sh腳本:
- ab -c 6 -n 6 http://localhost/limit
- sleep 1
- ab -c 6 -n 6 http://localhost/limit
- sleep 0.3
- ab -c 6 -n 6 http://localhost/limit
- sleep 0.3
- ab -c 6 -n 6 http://localhost/limit
- sleep 0.3
- ab -c 6 -n 6 http://localhost/limit
- sleep 2
- ab -c 6 -n 6 http://localhost/limit
將得到類似如下access.log輸出:
================================
[09/Jun/2016:14:30:11+0800] [1465453811.754] 200
[09/Jun/2016:14:30:11+0800] [1465453811.755] 200
[09/Jun/2016:14:30:11+0800] [1465453811.755] 200
[09/Jun/2016:14:30:11+0800] [1465453811.759] 200
[09/Jun/2016:14:30:11 +0800][1465453811.759] 503
[09/Jun/2016:14:30:11 +0800][1465453811.759] 503
[09/Jun/2016:14:30:12+0800] [1465453812.776] 200
[09/Jun/2016:14:30:12+0800] [1465453812.776] 200
[09/Jun/2016:14:30:12 +0800][1465453812.776] 503
[09/Jun/2016:14:30:12 +0800][1465453812.777] 503
[09/Jun/2016:14:30:12 +0800][1465453812.777] 503
[09/Jun/2016:14:30:12 +0800][1465453812.777] 503
[09/Jun/2016:14:30:13 +0800] [1465453813.095]503
[09/Jun/2016:14:30:13 +0800][1465453813.097] 503
[09/Jun/2016:14:30:13 +0800][1465453813.097] 503
[09/Jun/2016:14:30:13 +0800][1465453813.097] 503
[09/Jun/2016:14:30:13 +0800][1465453813.097] 503
[09/Jun/2016:14:30:13 +0800][1465453813.098] 503
[09/Jun/2016:14:30:13+0800] [1465453813.425] 200
[09/Jun/2016:14:30:13 +0800][1465453813.425] 503
[09/Jun/2016:14:30:13 +0800][1465453813.425] 503
[09/Jun/2016:14:30:13 +0800][1465453813.426] 503
[09/Jun/2016:14:30:13 +0800][1465453813.426] 503
[09/Jun/2016:14:30:13 +0800][1465453813.426] 503
[09/Jun/2016:14:30:13+0800] [1465453813.754] 200
[09/Jun/2016:14:30:13 +0800][1465453813.755] 503
[09/Jun/2016:14:30:13 +0800][1465453813.755] 503
[09/Jun/2016:14:30:13 +0800][1465453813.756] 503
[09/Jun/2016:14:30:13 +0800][1465453813.756] 503
[09/Jun/2016:14:30:13 +0800][1465453813.756] 503
[09/Jun/2016:14:30:15+0800] [1465453815.278] 200
[09/Jun/2016:14:30:15+0800] [1465453815.278] 200
[09/Jun/2016:14:30:15+0800] [1465453815.278] 200
[09/Jun/2016:14:30:15 +0800][1465453815.278] 503
[09/Jun/2016:14:30:15 +0800][1465453815.279] 503
[09/Jun/2016:14:30:15 +0800][1465453815.279] 503
[09/Jun/2016:14:30:17+0800] [1465453817.300] 200
[09/Jun/2016:14:30:17+0800] [1465453817.300] 200
[09/Jun/2016:14:30:17+0800] [1465453817.300] 200
[09/Jun/2016:14:30:17+0800] [1465453817.301] 200
[09/Jun/2016:14:30:17 +0800][1465453817.301] 503
[09/Jun/2016:14:30:17 +0800][1465453817.301] 503
桶容量為3(,即桶中在時(shí)間窗口內(nèi)最多流入3個(gè)請求,且按照2r/s的固定速率處理請求(即每隔500毫秒處理一個(gè)請求);桶計(jì)算時(shí)間窗口(1.5秒)=速率(2r/s)/桶容量(3),也就是說在這個(gè)時(shí)間窗口內(nèi)桶最多暫存3個(gè)請求。因此我們要以當(dāng)前時(shí)間往前推1.5秒和1秒來計(jì)算時(shí)間窗口內(nèi)的總請求數(shù);另外因?yàn)榕渲昧薾odelay,是非延遲模式,所以允許時(shí)間窗內(nèi)突發(fā)請求的;另外從本示例會看出兩個(gè)問題:
第一輪和第七輪:有4個(gè)請求處理成功了;這是因?yàn)橛?jì)算算法的問題,本示例是如果2秒內(nèi)沒有請求,然后接著突然來了很多請求,第一次計(jì)算的結(jié)果將是不正確的;這個(gè)問題影響很小可以忽略;
第五輪:1.0秒計(jì)算出來是3個(gè)請求;此處也是因計(jì)算精度的問題,也就是說limit_req實(shí)現(xiàn)的算法不是非常精準(zhǔn)的,假設(shè)此處看成相對于2.75的話,1.0秒內(nèi)只有1次請求,所以還是允許1次請求的。
如果限流出錯(cuò)了,可以配置錯(cuò)誤頁面:
- proxy_intercept_errors on;
- recursive_error_pages on;
- error_page 503 //www.jd.com/error.aspx;
limit_conn_zone/limit_req_zone定義的內(nèi)存不足,則后續(xù)的請求將一直被限流,所以需要根據(jù)需求設(shè)置好相應(yīng)的內(nèi)存大小。
此處的限流都是單Nginx的,假設(shè)我們接入層有多個(gè)nginx,此處就存在和應(yīng)用級限流相同的問題;那如何處理呢?一種解決辦法:建立一個(gè)負(fù)載均衡層將按照限流KEY進(jìn)行一致性哈希算法將請求哈希到接入層Nginx上,從而相同KEY的將打到同一臺接入層Nginx上;另一種解決方案就是使用Nginx+Lua(OpenResty)調(diào)用分布式限流邏輯實(shí)現(xiàn)。
lua-resty-limit-traffic
之前介紹的兩個(gè)模塊使用上比較簡單,指定KEY、指定限流速率等就可以了,如果我們想根據(jù)實(shí)際情況變化KEY、變化速率、變化桶大小等這種動態(tài)特性,使用標(biāo)準(zhǔn)模塊就很難去實(shí)現(xiàn)了,因此我們需要一種可編程來解決我們問題;而OpenResty提供了lua限流模塊lua-resty-limit-traffic,通過它可以按照更復(fù)雜的業(yè)務(wù)邏輯進(jìn)行動態(tài)限流處理了。其提供了limit.conn和limit.req實(shí)現(xiàn),算法與nginx limit_conn和limit_req是一樣的。
此處我們來實(shí)現(xiàn)ngx_http_limit_req_module中的【場景2.2測試】,不要忘記下載lua-resty-limit-traffic模塊并添加到OpenResty的lualib中。
配置用來存放限流用的共享字典:
- lua_shared_dict limit_req_store 100m;
以下是實(shí)現(xiàn)【場景2.2測試】的限流代碼limit_req.lua:
- local limit_req = require "resty.limit.req"
- local rate = 2 --固定平均速率 2r/s
- local burst = 3 --桶容量
- local error_status = 503
- local nodelay = false --是否需要不延遲處理
- local lim, err = limit_req.new("limit_req_store", rate, burst)
- if not lim then --沒定義共享字典
- ngx.exit(error_status)
- end
- local key = ngx.var.binary_remote_addr --IP維度的限流
- --流入請求,如果請求需要被延遲則delay > 0
- local delay, err = lim:incoming(key, true)
- if not delay and err == "rejected" then --超出桶大小了
- ngx.exit(error_status)
- end
- if delay > 0 then --根據(jù)需要決定是延遲或者不延遲處理
- if nodelay then
- --直接突發(fā)處理了
- else
- ngx.sleep(delay) --延遲處理
- end
- end
即限流邏輯再nginx access階段被訪問,如果不被限流繼續(xù)后續(xù)流程;如果需要被限流要么sleep一段時(shí)間繼續(xù)后續(xù)流程,要么返回相應(yīng)的狀態(tài)碼拒絕請求。
在分布式限流中我們使用了簡單的Nginx+Lua進(jìn)行分布式限流,有了這個(gè)模塊也可以使用這個(gè)模塊來實(shí)現(xiàn)分布式限流。
另外在使用Nginx+Lua時(shí)也可以獲取ngx.var.connections_active進(jìn)行過載保護(hù),即如果當(dāng)前活躍連接數(shù)超過閾值進(jìn)行限流保護(hù)。
- if tonumber(ngx.var.connections_active) >= tonumber(limit) then
- //限流
- end
nginx也提供了limit_rate用來對流量限速,如limit_rate 50k,表示限制下載速度為50k。
到此筆者在工作中涉及的限流用法就介紹完,這些算法中有些允許突發(fā),有些會整形為平滑,有些計(jì)算算法簡單粗暴;其中令牌桶算法和漏桶算法實(shí)現(xiàn)上是類似的,只是表述的方向不太一樣,對于業(yè)務(wù)來說不必刻意去區(qū)分它們;因此需要根據(jù)實(shí)際場景來決定如何限流,最好的算法不一定是最適用的。
參考資料
https://en.wikipedia.org/wiki/Token_bucket
https://en.wikipedia.org/wiki/Leaky_bucket
http://redis.io/commands/incr
http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html
https://github.com/openresty/lua-resty-limit-traffic
http://nginx.org/en/docs/http/ngx_http_core_module.html#limit_rate
【本文是專欄作者張開濤的原創(chuàng)文章,作者微信公眾號:開濤的博客( kaitao-1234567)】
網(wǎng)站標(biāo)題:聊聊高并發(fā)系統(tǒng)之限流特技-2
網(wǎng)站URL:http://fisionsoft.com.cn/article/dpdopoe.html


咨詢
建站咨詢
