nginx限流&健康檢查

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。
後端默認配置
 
前端請求:
請求屢次,後端服務均有日誌產生
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;">html



相關文章
相關標籤/搜索