
您好,我是湘王,這是我的51CTO博客,歡迎您來,歡迎您再來~
在互聯(lián)網(wǎng)應(yīng)用中,很多場景都會涉及到高并發(fā)請求,如果不對這些請求做限制,那么服務(wù)器很快就會被擠垮。就像在12306買票一樣,如果全國人民都去搶票,服務(wù)器是無論如何也扛不住壓力的。
這是非常現(xiàn)實的而且也是必須要解決的問題。
(資料圖片)
其實,除了反向代理和負(fù)載均衡,網(wǎng)絡(luò)限流也是Nginx的拿手好戲。
常用于實現(xiàn)網(wǎng)絡(luò)限流的兩類算法有:
1、令牌桶;
2、漏桶。
而Nginx實現(xiàn)限流的兩種方式是:
1、限制訪問頻率,就是限制指定時間內(nèi)每個用戶的訪問次數(shù);
2、限制并發(fā)連接數(shù),就是限制某段時間內(nèi)訪問資源的用戶數(shù)。
Nginx限流模塊使用的是漏桶算法。
令牌桶限流的算法思想是:
1、令牌以固定速率產(chǎn)生,并緩存到令牌桶;
2、令牌桶放滿時,多余的令牌將被直接丟棄;
3、請求進來時,先進入待處理的請求隊列;
4、處理請求時需要從桶里拿到相應(yīng)數(shù)量的令牌作為處理「憑證」;
5、當(dāng)桶里沒有令牌時,請求處理被拒絕。
令牌桶是一種常用于網(wǎng)絡(luò)流量整形和速率限制的算法,只有持有令牌的請求才會被處理,這也是令牌桶名稱的由來。令牌桶算法允許突發(fā)流量的存在,更適合會有突發(fā)流量的場景。
而漏桶限流的算法思想是:
水(請求)從上方進入水桶,從下方流出(被處理),來不及流出的水存在水桶中(緩沖),以固定速率流出。水桶滿后水溢出(丟棄請求)。漏桶也是一種常用的整形和限速算法,其核心是緩存請求、勻速處理、多余丟棄。
正如漏桶一樣,不管突然增加多少水量,底部的漏洞始終保持著勻速的出水量,這正是漏桶算法名稱的由來。因此漏桶算法會屏蔽突發(fā)請求,更適合需要平滑流量的場景。
漏桶算法與令牌桶算法看起來很類似,容易弄混。實際上這兩者具有截然不同的特性,應(yīng)用在不同的場景中。真正區(qū)分令牌桶和漏桶最核心的特征是「變速」和「勻速」:
1、令牌桶是一種變速運動——就像高速上的汽車一樣;
2、漏桶是一種勻速運動——就像鐵軌上的火車一樣。
這兩種限流算法沒有優(yōu)劣好壞之分,只區(qū)分場景的適用性。
為了驗證這兩種縣里算法,可以做一個簡單的測試。ab是apachebench命令的縮寫,是一款比較優(yōu)秀的壓測工具。在安裝Nginx的機器上安裝ab,如果不想安裝apache但是又想使用ab命令的話,可以這樣做:
yum -y install httpd-tools
cd /usr/bin
ab -V
ab的使用也很簡單:
./ab -h:獲取幫助
./ab -n1000 -c100 -t1 -s5 http://localhost/test?username=test1
意思是:發(fā)送1000次,每次100個并發(fā)請求到指定服務(wù),并在1秒之內(nèi)完成請求,超時時間5秒。如果只是-n100、-c10參數(shù),只能看到總的請求次數(shù)100次,看不到并發(fā)請求環(huán)境下是否真的滿足限流要求。
如果加上-t、-s參數(shù),就能很清楚地看到限流效果。
ab測試完成后的結(jié)果可能是這個樣子的:
用Nginx限制訪問速率可以這樣寫:限制每個IP的訪問速率為每秒10次。
limit_req_zone $binary_remote_addr zone=case1:10m rate=10r/s;
server {
listen 80;
server_name localhost;
location / {
limit_req zone=case1;
}
}
ab測試命令:
./ab -n100 -c10 -t1 -s5 http://localhost/test?username=test1
./ab -n100 -c10 -t2 -s5 http://localhost/test?username=test1(多線程影響)
結(jié)果滿足要求:
Complete requests:30397;Failed requests:30387
用Nginx限制突發(fā)增量可以這樣寫:限制每個IP的訪問速率為每秒10次,有burst且直接返回。
limit_req_zone $binary_remote_addr zone=case1:10m rate=10r/s;
server {
listen 80;
server_name localhost;
location / {
limit_req zone=case1 burst=5 nodelay;
}
}
ab測試命令:
./ab -n100 -c10 -t1 -s5 http://localhost/test?username=test1
./ab -n100 -c10 -t2 -s5 http://localhost/test?username=test1(多線程影響)
結(jié)果觀察:
Complete requests:15212;Failed requests:15197
用Nginx限制并發(fā)訪問:限制每個IP的并發(fā)請求為10。
limit_conn_zone $binary_remote_addr zone=case2:10m;
server {
listen 80;
server_name localhost;
location / {
limit_conn case2 10;
}
}
ab測試命令:
./ab -n100 -c10 -t1 -s5 http://localhost/test?username=test1
./ab -n100 -c11 -t1 -s5 http://localhost/test?username=test1
結(jié)果觀察:
當(dāng)參數(shù)為c10,所有請求全部成功;當(dāng)參數(shù)為c11,出現(xiàn)請求失敗的情況
限制并發(fā)訪問:按服務(wù)名。
限制每個服務(wù)的并發(fā)請求為10
limit_conn_zone $server_name zone=case3:10m;
server {
listen 80;
server_name localhost;
location / {
limit_conn case3 10;
}
}
ab測試命令:
./ab -n100 -c10 -t1 -s5 http://localhost/test?username=test1
./ab -n100 -c11 -t1 -s5 http://localhost/test?username=test1
結(jié)果觀察:
當(dāng)參數(shù)為c10,所有請求全部成功;當(dāng)參數(shù)為c11,出現(xiàn)請求失敗的情況
還可以自定義返回值:配置status返回值
limit_req_zone $binary_remote_addr zone=case1:10m rate=10r/s;
server {
listen 80;
server_name localhost;
location / {
limit_conn case1 10;
limit_req_status 599;
}
}
ab測試命令:
./ab -n100 -c10 -t1 -s5 http://localhost/test?username=test1
ab看不到效果,需要用其他更專業(yè)測試工具,比如Postman。
感謝您的大駕光臨!咨詢技術(shù)、產(chǎn)品、運營和管理相關(guān)問題,請關(guān)注后留言。歡迎騷擾,不勝榮幸~
?