轉自http://www.iyunv.com/thread-38535-1-1.html
公司業務線上對後端節點的健康檢查是通過nginx_upstream_check_module子產品做的,這裡我将分别介紹這三種實作方式以及之間的差異性。
一、ngx_http_proxy_module 子產品和ngx_http_upstream_module子產品(自帶)
嚴格來說,nginx自帶是沒有針對負載均衡後端節點的健康檢查的,但是可以通過預設自帶的ngx_http_proxy_module 子產品和ngx_http_upstream_module子產品中的相關指令來完成當後端節點出現故障時,自動切換到健康節點來提供通路。
這裡列出這兩個子產品中相關的指令:
ngx_http_proxy_module 子產品中的 proxy_connect_timeout 指令、proxy_read_timeout指令和proxy_next_upstream指令
1
2
3
文法: proxy_connect_timeout time;
預設值: proxy_connect_timeout 60s;
上下文: http, server, location
設定與後端伺服器建立連接配接的逾時時間。應該注意這個逾時一般不可能大于75秒。
文法: proxy_read_timeout time;
預設值: proxy_read_timeout 60s;
定義從後端伺服器讀取響應的逾時。此逾時是指相鄰兩次讀操作之間的最長時間間隔,而不是整個響應傳輸完成的最長時間。如果後端伺服器在逾時時間段内沒有傳輸任何資料,連接配接将被關閉。
文法: proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 |http_404 | off ...;
預設值: proxy_next_upstream error timeout;
指定在何種情況下一個失敗的請求應該被發送到下一台後端伺服器:
4
5
6
7
8
9
error # 和後端伺服器建立連接配接時,或者向後端伺服器發送請求時,或者從後端伺服器接收響應頭時,出現錯誤
timeout # 和後端伺服器建立連接配接時,或者向後端伺服器發送請求時,或者從後端伺服器接收響應頭時,出現逾時
invalid_header # 後端伺服器傳回空響應或者非法響應頭
http_500 # 後端伺服器傳回的響應狀态碼為500
http_502 # 後端伺服器傳回的響應狀态碼為502
http_503 # 後端伺服器傳回的響應狀态碼為503
http_504 # 後端伺服器傳回的響應狀态碼為504
http_404 # 後端伺服器傳回的響應狀态碼為404
off # 停止将請求發送給下一台後端伺服器
需要了解一點的是,隻有在沒有向用戶端發送任何資料以前,将請求轉給下一台後端伺服器才是可行的。也就是說,如果在傳輸響應到用戶端時出現錯誤或者逾時,這類錯誤是不可能恢複的。
範例如下:
http {
proxy_next_upstream http_502 http_504 http_404 error timeout invalid_header;
}
ngx_http_upstream_module子產品中的server指令
文法: server address [parameters];
預設值: —
上下文: upstream
upstream name {
server 10.1.1.110:8080 max_fails=1 fail_timeout=10s;
server 10.1.1.122:8080 max_fails=1 fail_timeout=10s;
}
下面是每個指令的介紹:
max_fails=number # 設定Nginx與伺服器通信的嘗試失敗的次數。在fail_timeout參數定義的時間段内,如果失敗的次數達到此值,Nginx就認為伺服器不可用。在下一個fail_timeout時間段,伺服器不會再被嘗試。 失敗的嘗試次數預設是1。設為0就會停止統計嘗試次數,認為伺服器是一直可用的。 你可以通過指令proxy_next_upstream、fastcgi_next_upstream和 memcached_next_upstream來配置什麼是失敗的嘗試。 預設配置時,http_404狀态不被認為是失敗的嘗試。
fail_timeout=time # 設定伺服器被認為不可用的時間段以及統計失敗嘗試次數的時間段。在這段時間中,伺服器失敗次數達到指定的嘗試次數,伺服器就被認為不可用。預設情況下,該逾時時間是10秒。
在實際應用當中,如果你後端應用是能夠快速重新開機的應用,比如nginx的話,自帶的子產品是可以滿足需求的。但是需要注意。如果後端有不健康節點,負載均衡器依然會先把該請求轉發給該不健康節點,然後再轉發給别的節點,這樣就會浪費一次轉發。
可是,如果當後端應用重新開機時,重新開機操作需要很久才能完成的時候就會有可能拖死整個負載均衡器。此時,由于無法準确判斷節點健康狀态,導緻請求handle住,出現假死狀态,最終整個負載均衡器上的所有節點都無法正常響應請求。由于公司的業務程式都是java開發的,是以後端主要是nginx叢集和tomcat叢集。由于tomcat重新開機應部署上面的業務不同,有些業務啟動初始化時間過長,就會導緻上述現象的發生,是以不是很建議使用該模式。
并且ngx_http_upstream_module子產品中的server指令中的max_fails參數設定值,也會和ngx_http_proxy_module 子產品中的的proxy_next_upstream指令設定起沖突。比如如果将max_fails設定為0,則代表不對後端伺服器進行健康檢查,這樣還會使fail_timeout參數失效(即不起作用)。此時,其實我們可以通過調節ngx_http_proxy_module 子產品中的 proxy_connect_timeout 指令、proxy_read_timeout指令,通過将他們的值調低來發現不健康節點,進而将請求往健康節點轉移。
以上就是nginx自帶的兩個和後端健康檢查相關的子產品。
二、nginx_upstream_check_module子產品
除了自帶的上述子產品,還有一個更專業的子產品,來專門提供負載均衡器内節點的健康檢查的。這個就是淘寶技術團隊開發的 nginx 子產品 nginx_upstream_check_module,通過它可以用來檢測後端 realserver 的健康狀态。如果後端 realserver 不可用,則是以的請求就不會轉發到該節點上。
如果我們沒有使用淘寶的 tengine 的話,可以通過更新檔的方式來添加該子產品到我們自己的 nginx 中。我們業務線上就是采用該方式進行添加的。
下面是部署流程!
1、下載下傳nginx_upstream_check_module子產品
[iyunv@localhost ~]# cd /usr/local/src
unzip master
[iyunv@localhost /usr/local/src]# ll -d nginx_upstream_check_module-master
drwxr-xr-x. 6 root root 4096 Dec 1 02:28 nginx_upstream_check_module-master
2、為nginx打更新檔
[iyunv@localhost /usr/local/src]# cd nginx-1.6.0 # 進入nginx的源碼目錄
[iyunv@localhost nginx-1.6.0]# patch -p1 < ../nginx_upstream_check_module-master/check_1.5.12+.patch
[iyunv@localhost nginx-1.6.0]# ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx-1.6.0 --with-http_ssl_module --with-openssl=/usr/local/src/openssl-0.9.8q --with-pcre=/usr/local/src/pcre-8.32 --add-module=/usr/local/src/nginx_concat_module/ --add-module=../nginx_upstream_check_module-master/
make (注意:此處隻make,編譯參數需要和之前的一樣)
[iyunv@localhost nginx-1.6.0]# mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx-1.6.0.bak
[iyunv@localhost nginx-1.6.0]# cp ./objs/nginx /usr/local/nginx/sbin/
[iyunv@localhost nginx-1.6.0]# /usr/local/nginx/sbin/nginx -t # 檢查下是否有問題
[iyunv@localhost nginx-1.6.0]# kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
3、在nginx.conf配置檔案裡面的upstream加入健康檢查,如下:
upstream name {
server 192.168.0.21:80;
server 192.168.0.22:80;
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
上面配置的意思是,對name這個負載均衡條目中的所有節點,每個3秒檢測一次,請求2次正常則标記 realserver狀态為up,如果檢測 5 次都失敗,則标記 realserver的狀态為down,逾時時間為1秒。
這裡列出nginx_upstream_check_module子產品所支援的指令意思:
Syntax: check interval=milliseconds [fall=count] [rise=count] [timeout=milliseconds] [default_down=true|false] [type=tcp|http|ssl_hello|mysql|ajp] [port=check_port]
Default: 如果沒有配置參數,預設值是:interval=30000 fall=5 rise=2 timeout=1000 default_down=true type=tcp
Context: upstream
該指令可以打開後端伺服器的健康檢查功能。
指令後面的參數意義是:
10
11
12
- interval:向後端發送的健康檢查包的間隔。
- fall(fall_count): 如果連續失敗次數達到fall_count,伺服器就被認為是down。
- rise(rise_count): 如果連續成功次數達到rise_count,伺服器就被認為是up。
- timeout: 後端健康請求的逾時時間。
- default_down: 設定初始時伺服器的狀态,如果是true,就說明預設是down的,如果是false,就是up的。預設值是true,也就是一開始伺服器認為是不可用,要等健康檢查包達到一定成功次數以後才會被認為是健康的。
- type:健康檢查包的類型,現在支援以下多種類型
- tcp:簡單的tcp連接配接,如果連接配接成功,就說明後端正常。
- ssl_hello:發送一個初始的SSL hello包并接受伺服器的SSL hello包。
- http:發送HTTP請求,通過後端的回複包的狀态來判斷後端是否存活。
- mysql: 向mysql伺服器連接配接,通過接收伺服器的greeting包來判斷後端是否存活。
- ajp:向後端發送AJP協定的Cping包,通過接收Cpong包來判斷後端是否存活。
- port: 指定後端伺服器的檢查端口。你可以指定不同于真實服務的後端伺服器的端口,比如後端提供的是443端口的應用,你可以去檢查80端口的狀态來判斷後端健康狀況。預設是0,表示跟後端server提供真實服務的端口一樣。該選項出現于Tengine-1.4.0。
Syntax: check_keepalive_requests request_num
Default: 1
該指令可以配置一個連接配接發送的請求數,其預設值為1,表示Tengine完成1次請求後即關閉連接配接。
Syntax: check_http_send http_packet
Default: "GET / HTTP/1.0\r\n\r\n"
該指令可以配置http健康檢查包發送的請求内容。為了減少傳輸資料量,推薦采用"HEAD"方法。
當采用長連接配接進行健康檢查時,需在該指令中添加keep-alive請求頭,如:"HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n"。 同時,在采用"GET"方法的情況下,請求uri的size不宜過大,確定可以在1個interval内傳輸完成,否則會被健康檢查子產品視為後端伺服器或網絡異常。
Syntax: check_http_expect_alive [ http_2xx | http_3xx | http_4xx | http_5xx ]
Default: http_2xx | http_3xx
該指令指定HTTP回複的成功狀态,預設認為2XX和3XX的狀态是健康的。
Syntax: check_shm_size size
Default: 1M
Context: http
所有的後端伺服器健康檢查狀态都存于共享記憶體中,該指令可以設定共享記憶體的大小。預設是1M,如果你有1千台以上的伺服器并在配置的時候出現了錯誤,就可能需要擴大該記憶體的大小。
Syntax: check_status [html|csv|json]
Default: check_status html
Context: location
顯示伺服器的健康狀态頁面。該指令需要在http塊中配置。
在Tengine-1.4.0以後,你可以配置顯示頁面的格式。支援的格式有: html、csv、 json。預設類型是html。
你也可以通過請求的參數來指定格式,假設‘/status’是你狀态頁面的URL, format參數改變頁面的格式,比如:
/status?format=html
/status?format=csv
/status?format=json
同時你也可以通過status參數來擷取相同伺服器狀态的清單,比如:
/status?format=html&status=down
/status?format=csv&status=up
下面是一個狀态也配置的範例:
server {
location /nstatus {
check_status;
access_log off;
#allow IP;
#deny all;
}
}
配置完畢後,重新開機nginx。此時通過通路定義好的路徑,就可以看到目前 realserver 實時的健康狀态啦。效果如下圖:
realserver 都正常的狀态:

一台 realserver 故障的狀态:
OK,以上nginx_upstream_check_module子產品的相關資訊,更多的資訊大家可以去該子產品的淘寶tengine頁面和github上該項目頁面去檢視,下面是通路位址:
http://tengine.taobao.org/document_cn/http_upstream_check_cn.html
https://github.com/yaoweibin/nginx_upstream_check_module
在生産環境的實施應用中,需要注意的有 2 點:
1、主要定義好type。由于預設的type是tcp類型,是以假設你服務啟動,不管是否初始化完畢,它的端口都會起來,是以此時前段負載均衡器為認為該服務已經可用,其實是不可用狀态。
2、注意check_http_send值的設定。由于它的預設值是"GET / HTTP/1.0\r\n\r\n"。假設你的應用是通過http://ip/name通路的,那麼這裡你的check_http_send值就需要更改為"GET /name HTTP/1.0\r\n\r\n"才可以。針對采用長連接配接進行檢查的,這裡增加keep-alive請求頭,即"HEAD /name HTTP/1.1\r\nConnection: keep-alive\r\n\r\n"。如果你後端的tomcat是基于域名的多虛拟機,此時你需要通過check_http_send定義host,不然每次通路都是失敗,範例:check_http_send "GET /mobileapi HTTP/1.0\r\n HOST www.redhat.sx\r\n\r\n";
三、ngx_http_healthcheck_module子產品
除了上面兩個子產品,nginx官方在早期的時候還提供了一個 ngx_http_healthcheck_module 子產品用來進行nginx後端節點的健康檢查。nginx_upstream_check_module子產品就是參照該子產品的設計理念進行開發的,是以在使用和效果上都大同小異。但是需要注意的是,ngx_http_healthcheck_module 子產品僅僅支援nginx的1.0.0版本,1.1.0版本以後都不支援了!是以,對于目前常見的生産環境上都不會去用了,這裡僅僅留個紀念,給大家介紹下這個子產品!
具體的使用方法,這裡可以貼出幾篇靠譜的博文位址以及官方位址:
https://github.com/cep21/healthcheck_nginx_upstreams/blob/master/README若轉載請注明出處!若有疑問,請回複交流!