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;">
