Nginx?限流和流量控制的實(shí)現(xiàn)
Nginx 提供了強(qiáng)大的流量控制功能。限制客戶端在特定時(shí)間段內(nèi)的請(qǐng)求次數(shù),以保護(hù)服務(wù)器資源,防止因過載而導(dǎo)致的性能下降甚至服務(wù)不可用。限流在防止DDoS攻擊、爬蟲過度抓取和濫用API等方面有著重要作用。這里將詳細(xì)介紹Nginx限流的工作原理、配置方法、各種限流策略以及實(shí)際應(yīng)用。
一、Nginx限流的工作原理
Nginx的限流功能主要通過limit_req
和limit_conn
模塊實(shí)現(xiàn):
limit_req
模塊: 用于限制每秒的請(qǐng)求次數(shù)。該模塊基于令牌桶(Token Bucket)算法,每個(gè)請(qǐng)求在處理前必須從令牌桶中獲取一個(gè)令牌,如果沒有令牌可用,則請(qǐng)求被延遲或拒絕。limit_conn
模塊: 用于限制同時(shí)連接數(shù)。該模塊控制每個(gè)特定鍵(如IP地址或用戶)允許的最大并發(fā)連接數(shù)。
二、limit_req模塊配置
limit_req
模塊通過定義共享內(nèi)存區(qū)域來存儲(chǔ)限流信息,并在特定的上下文中應(yīng)用限流策略。
1. 定義共享內(nèi)存區(qū)域
首先,需要定義一個(gè)共享內(nèi)存區(qū)域來存儲(chǔ)請(qǐng)求的計(jì)數(shù)信息。可以使用limit_req_zone
指令來完成。
語法:
limit_req_zone $variable zone=name:size rate=rate;
示例:
http { limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; server { location / { limit_req zone=one burst=5 nodelay; proxy_pass http://backend; } } }
在上面的示例中:
$binary_remote_addr
:以二進(jìn)制格式表示的客戶端IP地址。zone=one:10m
:定義名為one
的共享內(nèi)存區(qū)域,大小為10MB。rate=1r/s
:限制每秒最多1個(gè)請(qǐng)求。
2. 應(yīng)用限流策略
在定義共享內(nèi)存區(qū)域后,可以在server
或location
上下文中使用limit_req
指令來應(yīng)用限流策略。
語法:
limit_req zone=name [burst=number] [nodelay];
示例:
http { limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; server { location / { limit_req zone=one burst=5 nodelay; proxy_pass http://backend; } } }
在上面的示例中:
zone=one
:指定使用名為one
的共享內(nèi)存區(qū)域。burst=5
:允許突發(fā)5個(gè)請(qǐng)求。nodelay
:立即處理突發(fā)請(qǐng)求,不進(jìn)行延遲。
3. 示例配置詳解
以下是一個(gè)完整的示例配置:
http { # 定義共享內(nèi)存區(qū)域 limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; server { listen 80; server_name example.com; location / { # 應(yīng)用限流策略 limit_req zone=one burst=5 nodelay; # 代理到后端服務(wù)器 proxy_pass http://backend; 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_set_header X-Forwarded-Proto $scheme; } } }
在這個(gè)示例中,Nginx會(huì)限制每個(gè)客戶端每秒最多發(fā)送一個(gè)請(qǐng)求,并允許最多5個(gè)突發(fā)請(qǐng)求。
三、limit_conn模塊配置
limit_conn
模塊用于限制每個(gè)特定鍵(如IP地址或用戶)的并發(fā)連接數(shù)。
1. 定義共享內(nèi)存區(qū)域
首先,需要定義一個(gè)共享內(nèi)存區(qū)域來存儲(chǔ)連接計(jì)數(shù)信息??梢允褂?code>limit_conn_zone指令來完成。
語法:
limit_conn_zone $variable zone=name:size;
示例:
http { limit_conn_zone $binary_remote_addr zone=addr:10m; server { location / { limit_conn addr 10; proxy_pass http://backend; } } }
在上面的示例中:
$binary_remote_addr
:以二進(jìn)制格式表示的客戶端IP地址。zone=addr:10m
:定義名為addr
的共享內(nèi)存區(qū)域,大小為10MB。
2. 應(yīng)用限流策略
在定義共享內(nèi)存區(qū)域后,可以在server
或location
上下文中使用limit_conn
指令來應(yīng)用限流策略。
語法:
limit_conn zone_name number;
示例:
http { limit_conn_zone $binary_remote_addr zone=addr:10m; server { location / { limit_conn addr 10; proxy_pass http://backend; } } }
在上面的示例中:
zone_name
:指定使用的共享內(nèi)存區(qū)域名稱。number
:允許的最大并發(fā)連接數(shù)。
3. 示例配置詳解
以下是一個(gè)完整的示例配置:
http { # 定義共享內(nèi)存區(qū)域 limit_conn_zone $binary_remote_addr zone=addr:10m; server { listen 80; server_name example.com; location / { # 應(yīng)用限流策略 limit_conn addr 10; # 代理到后端服務(wù)器 proxy_pass http://backend; 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_set_header X-Forwarded-Proto $scheme; } } }
在這個(gè)示例中,Nginx會(huì)限制每個(gè)客戶端最多允許10個(gè)并發(fā)連接。
四、高級(jí)限流策略
1. 多級(jí)限流
在實(shí)際應(yīng)用中,可以根據(jù)不同的需求設(shè)置多級(jí)限流策略。例如,可以根據(jù)客戶端IP地址限制每秒請(qǐng)求數(shù),同時(shí)根據(jù)用戶ID限制每分鐘請(qǐng)求數(shù)。
示例:
http { limit_req_zone $binary_remote_addr zone=ip_zone:10m rate=1r/s; limit_req_zone $cookie_userid zone=user_zone:10m rate=30r/m; server { location / { limit_req zone=ip_zone burst=5 nodelay; limit_req zone=user_zone burst=10; proxy_pass http://backend; } } }
在上面的示例中:
ip_zone
:限制每個(gè)IP地址每秒最多1個(gè)請(qǐng)求,允許5個(gè)突發(fā)請(qǐng)求。user_zone
:限制每個(gè)用戶每分鐘最多30個(gè)請(qǐng)求,允許10個(gè)突發(fā)請(qǐng)求。
2. 動(dòng)態(tài)限流
通過Lua腳本和ngx_lua
模塊,可以實(shí)現(xiàn)更復(fù)雜的動(dòng)態(tài)限流策略。例如,可以根據(jù)用戶的VIP等級(jí)動(dòng)態(tài)調(diào)整限流閾值。
示例:
http { lua_shared_dict my_limit_req_store 10m; server { location / { access_by_lua_block { local limit_req = require "resty.limit.req" local lim, err = limit_req.new("my_limit_req_store", 200, 100) if not lim then ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err) return ngx.exit(500) end local key = ngx.var.binary_remote_addr local delay, err = lim:incoming(key, true) if not delay then if err == "rejected" then return ngx.exit(503) end ngx.log(ngx.ERR, "failed to limit req: ", err) return ngx.exit(500) end if delay >= 0.001 then ngx.sleep(delay) end } proxy_pass http://backend; } } }
在上面的示例中,使用了OpenResty的resty.limit.req
模塊,通過Lua腳本實(shí)現(xiàn)了動(dòng)態(tài)限流策略。
五、實(shí)際應(yīng)用場景
1. 防止DDoS攻擊
限流可以有效地防止DDoS攻擊。通過限制每個(gè)IP地址的請(qǐng)求頻率,可以防止惡意攻擊者發(fā)送大量請(qǐng)求導(dǎo)致服務(wù)器過載。
示例:
http { limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; server { location / { limit_req zone=one burst=5 nodelay; proxy_pass http://backend; } } }
2. 防止爬蟲過度抓取
通過限
流,可以防止爬蟲過度抓取網(wǎng)站內(nèi)容,從而保護(hù)服務(wù)器資源。
示例:
http { limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; server { location / { limit_req zone=one burst=5 nodelay; proxy_pass http://backend; } } }
3. 保護(hù)API服務(wù)
對(duì)于API服務(wù),限流可以防止濫用,確保API的可用性和穩(wěn)定性。
示例:
http { limit_req_zone $binary_remote_addr zone=one:10m rate=10r/m; server { location /api { limit_req zone=one burst=20 nodelay; proxy_pass http://api_backend; } } }
六、限流日志和監(jiān)控
為了更好地管理和監(jiān)控限流策略,可以配置Nginx的日志記錄限流事件,并使用監(jiān)控工具進(jìn)行分析。
1. 配置日志
可以通過Nginx的日志模塊記錄限流事件。
示例:
http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" ' '$request_time $upstream_response_time $pipe'; access_log /var/log/nginx/access.log main; limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; server { location / { limit_req zone=one burst=5 nodelay; error_log /var/log/nginx/error.log warn; proxy_pass http://backend; } } }
2. 使用監(jiān)控工具
可以使用Prometheus、Grafana等監(jiān)控工具來監(jiān)控Nginx的限流情況。通過配置Nginx的VTS
模塊,可以導(dǎo)出Nginx的各種統(tǒng)計(jì)信息,并在Grafana中進(jìn)行可視化展示。
到此這篇關(guān)于Nginx 限流和流量控制的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Nginx 限流和流量控制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Nginx+Tomcat實(shí)現(xiàn)動(dòng)靜分離的項(xiàng)目實(shí)踐
本文主要介紹了Nginx+Tomcat實(shí)現(xiàn)動(dòng)靜分離,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-01-01nginx訪問動(dòng)態(tài)接口報(bào)錯(cuò)404Not Found問題解決
本文主要介紹了nginx訪問動(dòng)態(tài)接口報(bào)錯(cuò)404Not Found問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03PHP(FastCGI)在Nginx的alias下出現(xiàn)404錯(cuò)誤的解決方法
這篇文章主要介紹了PHP(FastCGI)在Nginx的alias下出現(xiàn)404錯(cuò)誤的解決方法,涉及nginx平臺(tái)的相關(guān)配置技巧,需要的朋友可以參考下2016-05-05nginx編譯安裝后對(duì)nginx進(jìn)行平滑升級(jí)的方法
nginx編譯安裝后用了一段時(shí)間后發(fā)現(xiàn)當(dāng)前版本有漏洞或需要新的功能時(shí)就需要對(duì)當(dāng)前nginx版本進(jìn)行版本升級(jí),所以這時(shí)就需到對(duì)nginx的平滑升級(jí),如何進(jìn)行平滑升級(jí),下面就一起來了解一下2018-12-12nginx could not build the server_names_hash 解決方法
服務(wù)器名字的hash表是由指令 server_names_hash_max_size 和 server_names_hash_bucket_size所控制的。2011-03-03