1. 程式人生 > 實用技巧 >Nginx實戰-後端應用健康檢查

Nginx實戰-後端應用健康檢查

原文連結:http://nolinux.blog.51cto.com/4824967/1594029?utm_source=tuicool&utm_medium=referral

公司前一段對業務線上的nginx做了整理,重點就是對nginx上負載均衡器的後端節點做健康檢查。目前,nginx對後端節點健康檢查的方式主要有3種,這裡列出:

1 2 3 4 5 6 1、ngx_http_proxy_module模組和ngx_http_upstream_module模組(自帶) 官網地址:http://nginx.org/cn/docs/http/ngx_http_proxy_module.html
#proxy_next_upstream 2、nginx_upstream_check_module模組 官網網址:https://github.com/yaoweibin/nginx_upstream_check_module 3、ngx_http_healthcheck_module模組 官網網址:http://wiki.nginx.org/NginxHttpHealthcheckModule

公司業務線上對後端節點的健康檢查是通過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_timeouttime; 預設值: proxy_connect_timeout60s;
上下文: http,server,location

設定與後端伺服器建立連線的超時時間。應該注意這個超時一般不可能大於75秒。

1 2 3 語法: proxy_read_timeouttime; 預設值: proxy_read_timeout60s; 上下文: http,server,location

定義從後端伺服器讀取響應的超時。此超時是指相鄰兩次讀操作之間的最長時間間隔,而不是整個響應傳輸完成的最長時間。如果後端伺服器在超時時間段內沒有傳輸任何資料,連線將被關閉。

1 2 3 語法: proxy_next_upstreamerror|timeout|invalid_header|http_500|http_502|http_503|http_504|http_404|off...; 預設值: proxy_next_upstreamerrortimeout; 上下文: http,server,location

指定在何種情況下一個失敗的請求應該被髮送到下一臺後端伺服器:

1 2 3 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#停止將請求傳送給下一臺後端伺服器

需要理解一點的是,只有在沒有向客戶端傳送任何資料以前,將請求轉給下一臺後端伺服器才是可行的。也就是說,如果在傳輸響應到客戶端時出現錯誤或者超時,這類錯誤是不可能恢復的。

範例如下:

1 2 3 http{ proxy_next_upstreamhttp_502http_504http_404errortimeoutinvalid_header; }

ngx_http_upstream_module模組中的server指令

1 2 3 語法: serveraddress[parameters]; 預設值: — 上下文: upstream

範例如下:

1 2 3 4 upstreamname{ server10.1.1.110:8080max_fails=1fail_timeout=10s; server10.1.1.122:8080max_fails=1fail_timeout=10s; }

下面是每個指令的介紹:

1 2 3 4 5 6 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 上是自帶了該模組的,大家可以訪問淘寶tengine的官網來獲取該版本的nginx,官方地址:http://tengine.taobao.org/

如果我們沒有使用淘寶的 tengine 的話,可以通過補丁的方式來新增該模組到我們自己的 nginx 中。我們業務線上就是採用該方式進行新增的。

下面是部署流程!

1、下載nginx_upstream_check_module模組

1 2 3 4 5 [root@localhost~]#cd/usr/local/src wgethttps://codeload.github.com/yaoweibin/nginx_upstream_check_module/zip/master unzipmaster [root@localhost/usr/local/src]#ll-dnginx_upstream_check_module-master drwxr-xr-x.6rootroot4096Dec102:28nginx_upstream_check_module-master

2、為nginx打補丁

1 2 3 4 5 6 7 8 [root@localhost/usr/local/src]#cdnginx-1.6.0#進入nginx的原始碼目錄

給nginx打補丁(根據nginx版本號選擇補丁包)

[[email protected]]#patch-p1<../nginx_upstream_check_module-master/check_1.5.12+.patch

[[email protected]]#./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,編譯引數需要和之前的一樣) [[email protected]]#mv/usr/local/nginx/sbin/nginx/usr/local/nginx/sbin/nginx-1.6.0.bak [[email protected]]#cp./objs/nginx/usr/local/nginx/sbin/ [[email protected]]#/usr/local/nginx/sbin/nginx-t#檢查下是否有問題 [[email protected]]#kill-USR2`cat/usr/local/nginx/logs/nginx.pid`

3、在nginx.conf配置檔案裡面的upstream加入健康檢查,如下:

1 2 3 4 5 6 upstreamname{ server192.168.0.21:80; server192.168.0.22:80; checkinterval=3000rise=2fall=5timeout=1000type=http; }

上面配置的意思是,對name這個負載均衡條目中的所有節點,每個3秒檢測一次,請求2次正常則標記 realserver狀態為up,如果檢測 5 次都失敗,則標記 realserver的狀態為down,超時時間為1秒。

這裡列出nginx_upstream_check_module模組所支援的指令意思:

1 2 3 Syntax:checkinterval=milliseconds[fall=count][rise=count][timeout=milliseconds][default_down=true|false][type=tcp|http|ssl_hello|mysql|ajp][port=check_port] Default:如果沒有配置引數,預設值是:interval=30000fall=5rise=2timeout=1000default_down=truetype=tcp Context:upstream

該指令可以開啟後端伺服器的健康檢查功能。

指令後面的引數意義是:

1 2 3 4 5 6 7 8 9 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:傳送一個初始的SSLhello包並接受伺服器的SSLhello包。 -http:傳送HTTP請求,通過後端的回覆包的狀態來判斷後端是否存活。 -mysql:向mysql伺服器連線,通過接收伺服器的greeting包來判斷後端是否存活。 -ajp:向後端傳送AJP協議的Cping包,通過接收Cpong包來判斷後端是否存活。 -port:指定後端伺服器的檢查埠。你可以指定不同於真實服務的後端伺服器的埠,比如後端提供的是443埠的應用,你可以去檢查80埠的狀態來判斷後端健康狀況。預設是0,表示跟後端server提供真實服務的埠一樣。該選項出現於Tengine-1.4.0。
1 2 3 Syntax:check_keepalive_requestsrequest_num Default:1 Context:upstream

該指令可以配置一個連線傳送的請求數,其預設值為1,表示Tengine完成1次請求後即關閉連線。

1 2 3 Syntax:check_http_sendhttp_packet Default:"GET/HTTP/1.0\r\n\r\n" Context:upstream

該指令可以配置http健康檢查包傳送的請求內容。為了減少傳輸資料量,推薦採用"HEAD"方法。

當採用長連線進行健康檢查時,需在該指令中新增keep-alive請求頭,如:"HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n"。 同時,在採用"GET"方法的情況下,請求uri的size不宜過大,確保可以在1個interval內傳輸完成,否則會被健康檢查模組視為後端伺服器或網路異常。

1 2 3 Syntax:check_http_expect_alive[http_2xx|http_3xx|http_4xx|http_5xx] Default:http_2xx|http_3xx Context:upstream

該指令指定HTTP回覆的成功狀態,預設認為2XX和3XX的狀態是健康的。

1 2 3 Syntax:check_shm_sizesize Default:1M Context:http

所有的後端伺服器健康檢查狀態都存於共享記憶體中,該指令可以設定共享記憶體的大小。預設是1M,如果你有1千臺以上的伺服器並在配置的時候出現了錯誤,就可能需要擴大該記憶體的大小。

1 2 3 Syntax:check_status[html|csv|json] Default:check_statushtml Context:location

顯示伺服器的健康狀態頁面。該指令需要在http塊中配置。

在Tengine-1.4.0以後,你可以配置顯示頁面的格式。支援的格式有:html、csv、json。預設型別是html。

你也可以通過請求的引數來指定格式,假設‘/status’是你狀態頁面的URL,format引數改變頁面的格式,比如:

1 2 3 /status?format=html /status?format=csv /status?format=json

同時你也可以通過status引數來獲取相同伺服器狀態的列表,比如:

1 2 /status?format=html&status=down /status?format=csv&status=up

下面是一個狀態也配置的範例:

1 2 3 4 5 6 7 8 9 10 http{ server{ location/nstatus{ check_status; access_logoff; #allowIP; #denyall; } } }

配置完畢後,重啟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 HOSTwww.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版本以後都不支援了!因此,對於目前常見的生產環境上都不會去用了,這裡僅僅留個紀念,給大家介紹下這個模組!

具體的使用方法,這裡可以貼出幾篇靠譜的博文地址以及官方地址:

http://wiki.nginx.org/HttpHealthcheckModule

https://github.com/cep21/healthcheck_nginx_upstreams/blob/master/README

四、在nginx_upstream_check_module-master模組安裝正常的情況下,通過web介面檢視後端節點狀態配置方法,有問題請QQ聯絡我:405110958

1、配置upstream節點,並將健康監測頁面新增至該節點池內

upstream dvwa {
server 192.168.2.41:9000;
server 192.168.2.42:9000;
server 192.168.2.43:9000;
server 192.168.2.44:9000;
#check interval=5000 rise=1 fall=3 timeout=16000;
#check interval=3000 rise=2 fall=5 timeout=1000 type=ssl_hello;
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
check_keepalive_requests 100;
check_http_send "GET /dvwa/check.html HTTP/1.1\r\nHost:dvwa.manjd.com\r\nConnection: keep-alive\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
#check_http_send "HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n";

}

2、新增反向代理健康檢查節點

server
{
  listen 80;
  server_name dvwa.manjd.com;
  index index.html index.htm index.php;
location /status {
    check_status;
    access_log on;
    #allow SOME.IP.ADD.RESS;
    allow 10.0.0.0/8;
    allow 127.0.0.1/32;
    allow 192.168.0.0/16;
    #deny all;
}

location /ngx_status {

    stub_status on;
    allow 10.0.0.0/8;
    allow 127.0.0.1;
    allow 192.168.0.0/16;
    deny all;
}

location / {

    proxy_pass http://dvwa;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarder-For @proxy_add_x_forwarded_for;

}

}

3、web介面檢視健康狀態