Nginx原生限流模塊:
ngx_http_limit_conn_module模塊
根據前端請求域名或ip生成一個key,對於每個key對應的網絡連接數進行限制。
配置如下:
http模塊
server模塊
#http模塊內 http { include mime.types; default_type application/octet-stream; log_format main '[$time_local][$msec]$status'; sendfile on; keepalive_timeout 65; proxy_cache_path /var/nginx/cache keys_zone=one:10m levels=1:2 inactive=6h max_size=1g; ###限流配置 limit_conn_zone $binary_remote_addr zone=perip:10m; limit_conn_log_level info; limit_conn_status 503; include conf.d/*.conf; }
#server模塊內 server { listen 80; server_name _; root /opt/openresty/nginx/html; charset utf-8; proxy_send_timeout 60; proxy_read_timeout 1800s; client_max_body_size 300M ; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header Host $host:$server_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #---限流配置--# location /limit { limit_conn perip 2; proxy_pass http://backend/cache; } #-----------# error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } }
驗證:
采用ab測試:ab -n 10 -c 10 120.78.206.183/limit //並發數10個 總請求數10個
nginx:access.log日志

ab測試輸出:

ngx_http_limit_req_module模塊
利用漏桶算法實現。對於指定key進行限流,指定速率處理
配置
驗證:
#http模塊內 http { include mime.types; default_type application/octet-stream; log_format main '[$time_local][$msec]$status'; sendfile on; keepalive_timeout 65; proxy_cache_path /var/nginx/cache keys_zone=one:10m levels=1:2 inactive=6h max_size=1g; ###限流配置:每s處理一個請求 limit_req_zone $binary_remote_addr zone=req:10m rate=1r/s; limit_conn_log_level info; limit_conn_status 503; include conf.d/*.conf;
}
server { listen 80; server_name _; root /opt/openresty/nginx/html; charset utf-8; proxy_send_timeout 60; proxy_read_timeout 1800s; client_max_body_size 300M ; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header Host $host:$server_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #zone=one :設置使用哪個配置區域來做限制,與上面limit_req_zone 里的name對應 #burst=5:設置一個大小為5的緩沖區當有大量請求(爆發)過來時,超過了訪問頻次限制的請求可以先放到這個緩沖區內等待,但是這個等待區里的位置只有5個,超過的請求會直接報503的錯誤然后返回。 #nodelay: # 如果設置,會在瞬時提供處理(burst + rate)個請求的能力,請求超過(burst + rate)的時候就會直接返回503,永遠不存在請求需要等待的情況。(這里的rate的單位是:r/s) # 如果沒有設置,則所有請求會依次等待排隊 location /limit_req { limit_req zone=req burst=3 nodelay; proxy_pass http://backend/cache; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } }
采用ab測試:ab -n 10 -c 10 120.78.206.183/limit_req //並發數10個 總請求數10個

ab測試工具展示:

OpenResty限流模塊:
lua-resty-limit-traffic:
github: https://github.com/openresty/lua-resty-limit-traffic/tree/master/lib/resty/limit
包含四個模塊:
- conn:限制並發數
- count:給定時間窗口內通過固定數量的請求限制請求率
- req:請求速率限制
- traffic:可以自由組合多種限流策略
配置並發限流如下:
http { include mime.types; default_type application/octet-stream; log_format main '[$time_local][$msec]$status'; sendfile on; keepalive_timeout 65; lua_shared_dict my_limit_conn_store 100m; limit_conn_log_level info; limit_conn_status 503; include conf.d/*.conf; }
server { listen 80; server_name _; root /opt/openresty/nginx/html; charset utf-8; proxy_send_timeout 60; proxy_read_timeout 1800s; client_max_body_size 300M ; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header Host $host:$server_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #限制接口總並發數 location /limit_lua_conn { access_by_lua_block { local limit_conn = require "resty.limit.conn" -- 限制一個 ip 客戶端最大 1 個並發請求 -- burst 設置為 0,如果超過最大的並發請求數,則直接返回503, -- 如果此處要允許突增的並發數,可以修改 burst 的值(漏桶的桶容量) -- 最后一個參數其實是你要預估這些並發(或者說單個請求)要處理多久,以便於對桶里面的請求應用漏桶算法 local lim, err = limit_conn.new("my_limit_conn_store",2,1,0.5) if not lim then ngx.log(ngx.ERR,"限流:",err) return ngx.exit(503) 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 } proxy_pass http://backend/cache; } # error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } }
驗證結果:
ab -n 10 -c 10 120.78.206.183/limit_lua_conn
nginx日志:

ab結果:

Nginx健康檢查機制
nginx默認檢查機制
測試:后端兩台服務器:
max_fails:定義定義可以發生錯誤的最大次數
fail_timeout:nginx在fail_timeout設定的時間內與后端服務器通信失敗的次數超過max_fails設定的次數,則認為這個服務器不在起作用;在接下來的 fail_timeout時間內,nginx不再將請求分發給失效的server。
fail_timeout:nginx在fail_timeout設定的時間內與后端服務器通信失敗的次數超過max_fails設定的次數,則認為這個服務器不在起作用;在接下來的 fail_timeout時間內,nginx不再將請求分發給失效的server。
后端默認配置

前端請求:

請求多次,后端服務均有日志產生
120.78.206.183機器

14.116.196.138機器

停掉一台
14.116.196.138,請求正常返回:

nginx日志:

結論:
1.nginx健康檢查機制為被動檢查。
2.
在fail_timeout時間內,如果服務器節點在請求max_fails次數
都不返回,在這
fail_timeout
內,請求不會向這台服務器轉發,fail_timeout指定的超時時間到了,再次發起請求,就按照輪轉規則,該到這台服務器還是會過去,這時候再經歷
fail_timeout指定時間
,請求不會到這台服務器
Nginx第三方模塊健康檢查模塊:
主動檢查:
第三方模塊:
1.
nginx_upstream_check_module
主要配置:
upstream name{ server 192.168.0.21:80; server 192.168.0.22:80; check interval=3000 rise=2 fall=5 timeout=1000; } #對所有節點,每個3秒檢測一次,請求2次正常則標記 realserver狀態為up,如果檢測 5 次都失敗,則標記 realserver的狀態為down,超時時間為1秒
2.openresty模塊:lua-resty-upstream-healthcheck
http { upstream backend { server 120.78.206.183:8080; server 14.116.196.138:8002; } lua_shared_dict healthcheck 1m; lua_socket_log_errors off; init_worker_by_lua_block { local hc = require "resty.upstream.healthcheck" local ok, err = hc.spawn_checker { shm = "healthcheck", upstream = "tomcat", type = "http", #指定后端健康檢查http請求接口 http_req = "GET /nginx HTTP/1.0\r\nHost: tomcat\r\n\r\n", interval = 2000, timeout = 5000, fall = 3, rise = 2, #http請求接口返回200,302表示服務端正常 valid_statuses = {200, 302}, concurrency = 1, } if not ok then ngx.log(ngx.ERR, "=======> failed to spawn health checker: ", err) return end } server { listen 80; server_name localhost; location ^~ /cache { proxy_cache one; proxy_no_cache $http_soapaction; proxy_cache_key $request_body; proxy_cache_valid 200 302 10m; proxy_cache_methods GET POST; proxy_ignore_headers Cache-Control Set-Cookie; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://backend/cache; } location /server/status { access_log off; default_type text/plain; content_by_lua_block { local hc = require "resty.upstream.healthcheck" ngx.say("Nginx Worker PID: ", ngx.worker.pid()) ngx.print(hc.status_page()) } } } }
配置2s時間間隔探測:
access.log:


在nginx訪問日志中每隔2s健康檢查請求一次
kill掉任意一台后端服務:

nginx error.log日志

會持續檢查指定3次:上面fall參數指定
請求nginx后端健康檢查探測接口

多次請求后端接口:error.log日志無變化,說明請求不會路由到down機器上
重啟啟動down機器,再次請求nginx探測接口

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">