使用Nginx實現限流

網上很多類似的文章,但可能沒有一些實際壓測的說明,這裏做簡單說明

配置


 #統一在http域中進行配置

 #限制請求

 limit_req_zone $uri zone=api_read:20m rate=50r/s;

 #按ip配置一個連接 zone

 limit_conn_zone $binary_remote_addr zone=perip_conn:10m;

 #按server配置一個連接 zone

 limit_conn_zone $server_name zone=perserver_conn:100m;

===== server =====

location / {

 if (!-e $request_filename){

  rewrite ^/(.*) /index.php last;

 }

 #請求限流排隊通過 burst默認是0

 limit_req zone=api_read burst=100;

 #連接數限制,每個IP併發請求爲50

 limit_conn perip_conn 50;

 #服務所限制的連接數(即限制了該server併發連接數量)

 limit_conn perserver_conn 200;

 #連接限速

 #limit_rate 100k;

}

壓測效果

1. 未限制

1000 個請求併發100 個客戶端

1000 個請求併發1000 個客戶端

併發100、1000,每秒能處理的請求數相近,因爲這次目的不是壓測nginx 性能,所以沒必要繼續往下壓,這裏壓測主要是跟後面限流後的數據做對比。

2. 配置限流


rate=50r/s  # 每秒新增50個令牌

burst=100  # 令牌桶一共有100個令牌 

perip_conn 50  # 每個IP最多併發50個連接

perserver_conn 200  # 限制該server併發連接數 

1000 個請求併發100 個客戶端

雖然請求沒有失敗,但是明顯地RPS 下降很明顯,請求等待耗時也比不限流要多。

總耗時接近19s,也就是說新增令牌應該是19*50=950,而再加上原來令牌桶有100個令牌,總數是1050個,且perserver_conn=200,按道理也是能夠承接100個客戶端的1000個請求。

10000 個請求併發100 個客戶端

同上,RPS也是接近50左右,請求沒有失敗,請求等待耗時跟上面一樣

總壓測耗時200s,新增令牌數:200*50=10000,沒毛病

10000 個請求併發1000 個客戶端

RPS漲到4k多,但是從壓測結果來看,接近99%的請求都是失敗的,也就是說4k多裏面接近99%都是失敗的請求

nginx 限制了該server最多隻能接受200個併發連接,所以只要nginx接收到的併發數小於200,nginx都能夠處理,但由於令牌桶的限制,nginx最多隻能同時處理100個請求,其餘的請求會進行排隊,並且會在每秒內在生成50個令牌提供給排隊中的請求。

3. 匹配指定路徑進行限流


upstream ykz-www {

 server 10.13.14.134:80;

}

server {

 listen 80;

 server_name www-test.yunkezan.com yunkezan.yaochufa.com www.yunkezan.cn yunkezan.com yunkezan.cn;

 error_log /data/logs/www.yunkezan.com.error.log;

 access_log /data/logs/www.yunkezan.com.access.log main;

 location / {

          proxy_pass http://ykz-www;

          proxy_set_header Host $host;

          proxy_set_header X-Real-IP $remote_addr;

          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

          proxy_buffer_size 4k;

          proxy_buffers 4 32k;

          proxy_busy_buffers_size 64k;

          proxy_temp_file_write_size 64k; 

 }

 location /front/index/specialDetails {

> > limit_req zone=api_read burst=100;

> > limit_conn perip_conn 50;

                limit_conn perserver_conn 200;

                proxy_pass http://ykz-www;

                proxy_set_header Host $host;

                proxy_set_header X-Real-IP $remote_addr;

                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

                proxy_buffer_size 4k;

                proxy_buffers 4 32k;

                proxy_busy_buffers_size 64k;

                proxy_temp_file_write_size 64k;

 }

 include vhost/common/ssl-yunkezan.com.conf;

}

以上配置可以針對/front/index/specialDetails 該url 下的所有請求進行限流,但是有個問題是:該url 下是產品的鏈接,而所有產品鏈接都是在該url下以產品id 進行區分,這樣限流相當於將所有產品都進行限流,如果有某個爆款產品把鏈接佔用完了,會影響其他常規產品的訪問。

正常一個產品鏈接:https://www-test.yunkezan.com/front/index/specialDetails?weChatId=421&goodId=17503&activityId=2027&channel=promoteMall&tag_id=-1&tag_name=%E9%99%90%E6%97%B6%E6%8A%A2%E8%B4%AD&tag2_id=-5&tag2_name=%E7%83%AD%E9%97%A8

返回503 被限流。

    #限制請求

    #limit_req_zone $uri zone=api_read:20m rate=50r/s;

    #按ip配置一個連接 zone

    #limit_conn_zone $binary_remote_addr zone=perip_conn:10m;

    #按server配置一個連接 zone

    #limit_conn_zone $server_name zone=perserver_conn:100m;

    #按goodId配置一個連接 zone
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章