nginx 訪問頻率控制

Nginx訪問頻率控制

HTTP服務器的吞吐率(單位時間吞吐量)一般有一個上限,尤爲是普通配置的機器,在帶寬夠的狀況下,用壓測工具常常能把服務器壓出翔,爲了線上環境穩定性,防止惡意攻擊影響到其餘用戶,可選擇對客戶端訪問頻率進行合理限制。html

限制原理

限制原理並不難,可一句話歸納爲:「根據客戶端特徵,限制其訪問頻率」,客戶端特徵主要指IP、UserAgent等。使用IP比UserAgent更可靠,由於IP沒法造假,UserAgent可隨意僞造。node

雖然IP沒法造假,但惡意人員能夠利用代理,所以僅依靠限制IP訪問頻率並不能應對大量代理的狀況,另外在限制IP訪問頻率時也要考慮多用戶共享網絡出口的狀況,好比校園網、企業局域網網絡之類。nginx

實踐

因爲存在盲區,不知道Nginx中有訪問控制模塊,想着本身在應用代碼中使用Redis實現基於IP的訪問頻率控制,在準備寫代碼以前發現Nginx有limit_req模塊可限制基於IP的訪問頻率,所以選擇Nginx,這確定比本身實現更省事,性能也更優秀。算法

limit_req_zone

Syntax:  limit_req_zone key zone=name:size rate=rate;
Default: —
Context: http
  • key,表示做爲限制的請求特徵,能夠包含文本與變量,IP場景使用$binary_remote_addr
  • name,zone的名稱,limit_req會用到
  • size,zone的大小,1M大小在64位系統可存儲8000個state(ip、count...),每次添加新state時,可能刪除至多兩個前60秒未使用的state,若添加新state時zone大小不夠,則刪除較舊的state,釋放空間後依舊不夠返回503
  • rate,訪問速率,支持秒或者分鐘爲單位,但nginx內部使用毫秒追蹤請求數,若是限制是10r/1s,其實是1r/100ms

limit_req

Syntax:  limit_req zone=name [burst=number] [nodelay];
Default: —
Context: http, server, location
  • name,limit_req_zone中配置的名稱
  • burst,可理解爲緩衝卡槽,若是設置則全部請求都經由緩衝卡槽轉發給upstream,一般可併發接收的請求數爲number + 1,但當number爲0時會拒絕全部請求
  • nodelay,緩衝卡槽中請求轉發給upstream的時機,不設置時,會按照zone的速率逐個轉發,當設置爲nodelay時,請求到達緩衝卡槽後會當即轉發給upstream,但卡槽中的佔位依舊按照頻率釋放

配置

理解limit_req_zonelimit_req以後,感嘆這真是個好設計,也知道它背後的形象的名稱:漏桶算法服務器

瞭解配置方式後開始實際操做,在Nginx配置中的http內添加:網絡

limit_req_zone $binary_remote_addr zone=one:2m rate=10r/s;

在須要限制的server內添加:併發

limit_req zone=one burst=10 nodelay;

按照官方文檔,2M大小在64位系統中大約可存儲16000個狀態數據,針對本身的我的網站足夠,10r/s即1r/100ms,配合burst=10應該也OK,重啓Nginx,而後使用壓測工具檢驗一下。工具

rate、burst、nodelay的不一樣特色:性能

排除其餘因素,rate的大小針對同一客戶端的平均吞吐率起到決定性做用,而burst與nodelay可根據業務需求選擇,burst越大可接收的併發請求越多,但rate跟不上可能致使大量客戶端請求超時,nodelay在rate較小時能夠提高業務在瞬時的吞吐率表現網站

白名單

之因此會限制IP訪問頻率,主要是爲了阻止外部調用者的惡意行爲,但通過上述配置後,對系統內部調用者一樣會有所限制,所以咱們但願將內部調用者列入白名單內,使其不受訪問頻率限制。

這主要藉助Nginx中的geo與map功能,經過geo將IP映射成值,而後再經過map將值映射成變量或常量,剛好limit_req_zone中若是key爲''表示不對其進行頻率限制,因此只須要將白名單用戶的key設置爲''

修改配置文件中http的內容:

geo $limit {
    default 1;
    127.0.0.1 0;     # 本機地址
    172.31.0.0/16 0; # 內網地址
}
 
map $limit $limit_key {
    0 "";
    1 $binary_remote_addr;
}

limit_req_zone $limit_key zone=one:2m rate=10r/s;

總結

至此,根據IP限制訪問頻率配置完成,Nginx中與limit_req相似的還有limit_conn,可用來在鏈接層面進行限制,同時針對limit_req還有兩個配置項limit_req_statuslimit_req_log_level,前者用來設置達到限制時返回何種狀態碼,後者制定達到限制時的日誌採用何種級別,會致使達到限制的信息出如今不一樣的日誌文件中。

從打算本身實現,到使用Nginx實現,感受本身的對服務器的理解還須要提高,應該從合理性角度就能夠推斷出Nginx包含該類功能,而不是在搜索的過程當中發現Nginx包含該功能。

ref https://amsimple.com/blog/article/47.html

相關文章
相關標籤/搜索