nginx之限流詳解(請求/并發(fā)量)
簡述
在做日常的web運維工作中,難免會遇到服務器流量異常,負載過大等情況。
惡意攻擊訪問/爬蟲等非正常性請求,會帶來帶寬的浪費,服務器壓力增大,影響業(yè)務質量。
限流方案
對于這種情況, 一般可考慮通過nginx的ngx_http_limit_conn_module模塊和ngx_http_limit_req_module 模塊限制同一client ip的請求量和并發(fā)數(shù)來防范。
1. ngx_http_limit_conn_module模塊(限制連接數(shù)[并發(fā)])
limit_conn_zone
- 語法: limit_conn_zone $variable zone=name:size;
- 默認值: none
- 配置段: http
$variable定義鍵(鍵的狀態(tài)中保存了當前連接數(shù)),zone=name定義區(qū)域名稱,后面的limit_conn指令會用到的。
size定義各個鍵共享內存空間大小(當共享內存空間被耗盡,服務器將會對后續(xù)所有的請求返回 503 錯誤。)。
limit_conn_log_level
- 語法:limit_conn_log_level info | notice | warn | error
- 默認值:error
- 配置段:http, server, location
- 當達到最大限制連接數(shù)后,記錄日志的等級。
limit_conn
- 語法:limit_conn zone_name number
- 默認值:none
- 配置段:http, server, location
- 指定每個給定鍵值的最大同時連接數(shù),當超過這個數(shù)字時被返回503
limit_conn_status
- 語法: limit_conn_status code;
- 默認值: limit_conn_status 503;
- 配置段: http, server, location
- 該指定在1.3.15版本引入的。指定當超過限制時,返回的狀態(tài)碼。默認是503。
limit_rate
- 語法:limit_rate rate
- 默認值:0
- 配置段:http, server, location, if in location
對每個連接的速率限制。參數(shù)rate的單位是字節(jié)/秒,設置為0將關閉限速。
按連接限速而不是按IP限制,因此如果某個客戶端同時開啟了兩個連接,那么客戶端的整體速率是這條指令設置值的2倍。
2. ngx_http_limit_req_module模塊(限制請求數(shù))
limit_req_zone
- 語法: limit_req_zone $variable zone=name:size rate=rate;
- 默認值: none
- 配置段: http
設置一塊共享內存限制域用來保存鍵值的狀態(tài)參數(shù),速度可以設置為每秒處理請求數(shù)和每分鐘處理請求數(shù),其值必須是整數(shù),所以如果你需要指定每秒處理少于1個的請求,2秒處理一個請求,可以使用 “30r/m”
limit_req_log_level
- 語法: limit_req_log_level info | notice | warn | error;
- 默認值: limit_req_log_level error;
- 配置段: http, server, location
設置你所希望的日志級別
limit_req_status
- 語法: limit_req_status code;
- 默認值: limit_req_status 503;
- 配置段: http, server, location
limit_req
- 語法: limit_req zone=name [burst=number] [nodelay];
- 默認值: —
- 配置段: http, server, location
設置對應的共享內存限制域和允許被處理的最大請求數(shù)閾值。 如果請求的頻率超過了限制域配置的值,請求處理會被延遲,當被延遲的請求數(shù)超過了定義的閾值,這個請求會被終止,并返回503;nodelay:表示當超過訪問次數(shù)并緩沖也滿的情況下,直接放回503錯誤,若不設置,這些多余的請求會延遲處理 。
實際運用案例
一般情況下key使用$binary_remote_addr(建議使用)或者$remote_addr變量二者區(qū)別在于: $remote_addr變量的長度為7字節(jié)到15字節(jié),而存儲狀態(tài)在32位平臺中占用32字節(jié)或64字節(jié),在64位平臺中占用64字節(jié)。
$binary_remote_addr變量的長度是固定的4字節(jié),存儲狀態(tài)在32位平臺中占用32字節(jié)或64字節(jié),在64位平臺中占用64字節(jié)。
1M共享空間可以保存3.2萬個32位的狀態(tài),1.6萬個64位的狀態(tài)。當恭喜內存空間被耗盡時,服務會對后續(xù)請求返回503(切記).
http{
.........
limit_conn_zone $binary_remote_addr zone=addr:1000m;
limit_req_zone $binary_remote_addr zone=addrs:1000m rate=10r/s; #每秒請求10次
...........
server{
......
limit_conn addr 10; #限制并發(fā)數(shù)為10
limit_req zone=addrs burst=5 nodelay; #允許超出請求5(排隊/延遲)
......
}
}
#注 limit_conn_zone 和limit_req_zone可單獨使用除以上以$binary_remote_addr變量為key外,還有一種情況,如前端使用了代理層,CDN等服務,這種情況下$binary_remote_addr變量會是代理層/CDN的ip,就無法通過$binary_remote_addr變量做限制, 目前知道有兩種解決方式,一種是使用白名單, 另外一種是配置$http_x_forwarded_for然后取逗號分隔的第一個ip(即源ip,不太好的消息就是這個變量字段是可以通過修改請求head信息進行偽造(curl -H "X-Forwarded-For:192.168.0.1,192.168.0.2" http://127.0.0.1 ))。
白名單的方式后續(xù)再說。
這里先說下第二種方法, 可通過nginx的map模塊做正則匹配后映射請求源ip, 具體配置如下:
1)代理層的配置:
upstream renren_trans_1 {
server 10.5.11.12;
} server {
listen 80;
server_name zabbixtest.d.xiaonei.com;
http_accounting_id zabbixtest;
location / {
proxy_pass http://renren_trans_1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 50m;
client_body_buffer_size 128k;
client_body_temp_path /data/client_body_temp;
proxy_connect_timeout 15;
proxy_send_timeout 300;
proxy_read_timeout 300;
proxy_buffer_size 8k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_temp_path /data/proxy_temp;
}
}代理層后端(業(yè)務機)配置:
map $http_x_forwarded_for $clientips {
"" $remote_addr; #當為空時映射$remote_addr 到$clientips
~^(?P<firstip>[0-9\.]+),?.*$ $firstip; #獲取第一個ip
}
limit_conn_zone $clientips zone=addr:1000m;
limit_req_zone $clientips zone=addrs:1000m rate=10r/s;
limit_req zone=addrs burst=5 nodelay;
server {
listen 80;
server_name localhost;
limit_conn addr 10;
limit_req zone=addrs burst=5 nodelay;
#charset koi8-r;
#access_log logs/host.access.log main;測試:
1) 測試通過代理層訪問的方式:
# ab -c 11 -t 10 http://zabbixtest.d.xiaonei.com/test.html
access.log內容如下:
可發(fā)現(xiàn)大量503 error(第一列代理層,最后一列源ip) 。
2)測試直接訪問,不通過代理層
# ab -c 5 -t 10 http://10.5.11.12/test.html
access.log如下:
同樣會出現(xiàn)大量503 ,代理ip為空!
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
詳解Nginx反向代理實現(xiàn)Kibana登錄認證功能
這篇文章主要介紹了詳解Nginx反向代理實現(xiàn)Kibana登錄認證功能,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06
詳解Nginx服務器的nginx-http-footer-filter模塊配置
這篇文章主要介紹了Nginx服務器的nginx-http-footer-filter模塊配置,nginx-http-footer-filter用作在請求的頁面底部插入代碼,需要的朋友可以參考下2016-01-01
Nginx解決Http慢攻擊(Slow HTTP Attack)的方法
緩慢的HTTP拒絕服務攻擊是一種專門針對于Web的應用層拒絕服務攻擊,本文給大家介紹了Nginx解決Http慢攻擊(Slow HTTP Attack)的方法,需要的朋友可以參考下2024-02-02
在Linux中查看Apache或Nginx服務狀態(tài)的詳細步驟
在Linux中,查看Apache或Nginx服務的狀態(tài)通常涉及到使用系統(tǒng)管理工具或特定于這些Web服務器的命令,以下是如何查看Apache和Nginx服務狀態(tài)的詳細步驟,需要的朋友可以參考下2024-03-03

