大家都知道,前端nginx做反向代理,如果后端服務器宕掉的話,nginx是不能把這台real server踢出upstream的,所以還會有請求轉發到后端的這台real server上面去,雖然nginx可以在localtion中啟用proxy_next_upstream來解決返回給用戶的錯誤頁面,但這個還是會把請求轉發給這台服務器的,然后再轉發給別的服務器,這樣就浪費了一次轉發,這次借助與淘寶技術團隊開發的nginx模快nginx_upstream_check_module來檢測后方realserver的健康狀態,如果后端服務器不可用,則所以的請求不轉發到這台服務器。
轉載於https://blog.csdn.net/qq_34556414/article/details/106636710
nginx_upstream_check_module模塊
nginx_upstream_check_module 是專門提供負載均衡器內節點的健康檢查的外部模塊,由淘寶的姚偉斌大神開發,通過它可以用來檢測后端 realserver 的健康狀態。如果后端 realserver 不可用,則后面的請求就不會轉發到該節點上,並持續檢查幾點的狀態。在淘寶自己的 tengine 上是自帶了該模塊。項目地址:https://github.com/yaoweibin/nginx_upstream_check_module 。
在淘寶自己的 tengine 上是自帶了該模塊的,大家可以訪問淘寶tengine的官網來獲取該版本的nginx,官方地址:http://tengine.taobao.org/。
nginx后端健康檢查
nginx自帶健康檢查的缺陷:
- Nginx只有當有訪問時后,才發起對后端節點探測。
- 如果本次請求中,節點正好出現故障,Nginx依然將請求轉交給故障的節點,然后再轉交給健康的節點處理。所以不會影響到這次請求的正常進行。但是會影響效率,因為多了一次轉發
- 自帶模塊無法做到預警
- 被動健康檢查
使用第三訪模塊nginx_upstream_check_module:
- 區別於nginx自帶的非主動式的心跳檢測,淘寶開發的tengine自帶了一個提供主動式后端服務器心跳檢測模塊
- 若健康檢查包類型為http,在開啟健康檢查功能后,nginx會根據設置的間隔向指定的后端服務器端口發送健康檢查包,並根據期望的HTTP回復狀態碼來判斷服務是否健康。
- 后端真實節點不可用,則請求不會轉發到故障節點
- 故障節點恢復后,請求正常轉發
nginx被動檢查
Nginx自帶有健康檢查模塊:ngx_http_upstream_module,可以做到基本的健康檢查,配置如下:
-
upstream cluster{
-
server 172.16.0.23:80 max_fails=1 fail_timeout=10s;
-
server 172.16.0.24:80 max_fails=1 fail_timeout=10s;
-
# max_fails=1和fail_timeout=10s 表示在單位周期為10s鍾內,中達到1次連接失敗,那么接將把節點標記為不可用,並等待下一個周期(同樣時常為fail_timeout)再一次去請求,判斷是否連接是否成功。
-
# fail_timeout為10s,max_fails為1次。
-
}
-
server {
-
listen 80;
-
server_name xxxxxxx.com;
-
location / {
-
proxy_pass http://cluster;
-
}
-
}
缺點:
Nginx只有當有訪問時后,才發起對后端節點探測。如果本次請求中,節點正好出現故障,Nginx依然將請求轉交給故障的節點,然后再轉交給健康的節點處理。所以不會影響到這次請求的正常進行。但是會影響效率,因為多了一次轉發,而且自帶模塊無法做到預警。
nginx主動檢查
主動地健康檢查,nignx定時主動地去ping后端的服務列表,當發現某服務出現異常時,把該服務從健康列表中移除,當發現某服務恢復時,又能夠將該服務加回健康列表中。淘寶有一個開源的實現nginx_upstream_check_module模塊
-
github地址: https://github.com/yaoweibin/nginx_upstream_check_module
-
taobao官網: http://tengine.taobao.org/document_cn/http_upstream_check_cn.html
安裝nginx_upstream_check_module
安裝擴展模塊,需要編譯安裝的nginx,版本自己選擇(我的是nginx version: nginx/1.16.1)
(1)獲取安裝包
-
[root@www src]# wget https://codeload.github.com/yaoweibin/nginx_upstream_check_module/zip/master
-
Saving to: ?.aster?
-
-
[ <=> ] 175,413 277KB/s in 0.6s
-
-
2020-09-28 10:36:44 (277 KB/s) - ?.aster?.saved [175413]
(2)給nginx打個補丁
(master解壓后的文件為nginx_upstream_check_module-master 里面包含了多個補丁版本,根據自己的nginx版本選擇)
-
[root@www src] # unzip master
-
[root@www src] # ls
-
debug kernels nginx- 1.16.1 nginx_upstream_check_module-master
-
master nginx- 1.16.1.tar.gz
-
-
#進入nginx-1.16.1源碼目錄,進行打該模塊的補丁(這一步千萬不能遺漏)
-
[root@www nginx- 1.16.1]# yum install patch-2.7.1-12.el7_7.x86_64 -y
-
[root@www nginx- 1.16.1]# patch -p1 < /usr/src/nginx_upstream_check_module-master/check_1.16.1+.patch
-
patching file src/http/modules/ngx_http_upstream_hash_module.c
-
patching file src/http/modules/ngx_http_upstream_ip_hash_module.c
-
patching file src/http/modules/ngx_http_upstream_least_conn_module.c
-
patching file src/http/ngx_http_upstream_round_robin.c
-
patching file src/http/ngx_http_upstream_round_robin.h
(3)編譯安裝
-
[ root@www nginx-1.16.1]# /usr/local/nginx/sbin/nginx -V
-
nginx version: nginx/1.16.1
-
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
-
configure arguments: --prefix=/usr/local/nginx
-
[ root@www nginx-1.16.1]# ./configure --prefix=/usr/local/nginx --add-module=/usr/src/nginx_upstream_check_module-master/
-
checking for OS
-
+ Linux 3.10.0-693.el7.x86_64 x86_64
-
checking for C compiler ... found
-
+ using GNU C compiler
-
+ gcc version: 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
-
-
[ root@www nginx-1.16.1]# make && make install
-
-
[ root@www nginx-1.16.1]# make upgrade
-
/usr/local/nginx/sbin/nginx -t
-
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
-
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
-
kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
-
sleep 1
-
test -f /usr/local/nginx/logs/nginx.pid.oldbin
-
kill -QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin`
-
-
[ root@www nginx-1.16.1]# /usr/local/nginx/sbin/nginx -V
-
nginx version: nginx/1.16.1
-
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
-
configure arguments: --prefix=/usr/local/nginx --add-module=/usr/src/nginx_upstream_check_module-master/
nginx_upstream_check_module模塊使用
服務治理的一個重要任務是感知服務節點變更,完成服務自動注冊
及異常節點的自動摘除
。這就需要服務治理平台能夠:及時
、准確
的感知service節點的健康狀況。
方案概述
Nginx 提供了三種HTTP服務健康檢查方案供用戶選擇:
-
TCP層默認檢查方案:
定時與后端服務建立一條
tcp連接
,鏈接建立成功則認為服務節點是健康的。 -
HTTP層默認檢查方案:
TCP層檢查有一定的局限性:
-
很多HTTP服務是帶狀態的,端口處於listen狀態並不能代表服務已經完成預熱;
-
不能真實反映服務內部處理邏輯是否產生擁堵。
-
這時可以選擇
http層
健康檢查,會向服務發送一個http請求GET / HTTP/1.0\r\n\r\n
,返回狀態是2xx或3xx時認為后端服務正常。
-
-
自定義方案:(nginx_upstream_check_module模塊)
可根據下文描述自定義檢查方案。
配置參數詳解
一個常用的健康檢查配置如下:
-
check fall=3 interval=3000 rise=2 timeout=2000 type=http;
-
check_http_expect_alive http_2xx http_3xx ;
-
check_http_send "GET /checkAlive HTTP/1.0\r\n\r\n" ;
下面針對每個配置參數,進行詳細介紹。
check:
check 字段參數如下:
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
check
字段各個參數含義如下:
-
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提供真實服務的端口一樣。
-
check_http_expect_alive:
check_http_expect_alive
指定主動健康檢查時HTTP回復的成功狀態:
-
Syntax: check_http_expect_alive
-
Default: http_2xx | http_3xx
check_http_send:
check_http_send
配置http健康檢查包發送的請求內容
為了減少傳輸數據量,推薦采用”HEAD”方法。當采用長連接進行健康檢查時,需在該指令中添加keep-alive請求頭,如:”HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n”。同時,在采用”GET”方法的情況下,請求uri的size不宜過大,確保可以在1個interval內傳輸完成,否則會被健康檢查模塊視為后端服務器或網絡異常。
-
Syntax: check_http_send http_packet
-
Default: "GET / HTTP/1.0\r\n\r\n"
完整示例
完整示例,如下:
http {
-
upstream cluster1 {
-
# simple round-robin
-
server 192.168.0.1:80;
-
server 192.168.0.2:80;
-
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
-
check_http_send "HEAD / HTTP/1.0\r\n\r\n";
-
check_http_expect_alive http_2xx http_3xx;
-
}
-
upstream cluster2 {
-
# simple round-robin
-
server 192.168.0.3:80;
-
server 192.168.0.4:80;
-
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
-
check_keepalive_requests 100;
-
check_http_send "HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n";
-
check_http_expect_alive http_2xx http_3xx;
-
}
-
server {
-
listen 80;
-
location /1 {
-
proxy_pass http://cluster1;
-
}
-
location /2 {
-
proxy_pass http://cluster2;
-
}
-
location / status {
-
check_status;
-
access_log off;
-
allow SOME.IP.ADD.RESS;
-
deny all;
-
}
-
}
-
}
狀態測試
-
[ root@www ~]# /usr/local/tomcat/bin/shutdown.sh
-
Using CATALINA_BASE: /usr/local/tomcat
-
Using CATALINA_HOME: /usr/local/tomcat
-
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
-
Using JRE_HOME: /usr/java/jdk1.8.0_131
-
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
-
-
-
[ root@www ~]# tail -f /usr/local/nginx/logs/error.log
-
2020/09/28 11:18:38 [notice] 8400#0: using inherited sockets from "6;"
-
2020/09/28 11:21:05 [notice] 8409#0: signal process started
-
2020/09/28 11:33:37 [notice] 8419#0: signal process started
-
2020/09/28 11:33:42 [error] 8420#0: enable check peer: 192.168.179.100:8080
-
2020/09/28 11:51:23 [error] 8420#0: send() failed (111: Connection refused)
-
2020/09/28 11:51:26 [error] 8420#0: send() failed (111: Connection refused)
-
2020/09/28 11:51:29 [error] 8420#0: send() failed (111: Connection refused)
-
2020/09/28 11:51:32 [error] 8420#0: send() failed (111: Connection refused)
-
2020/09/28 11:51:35 [error] 8420#0: send() failed (111: Connection refused)
-
2020/09/28 11:51:35 [error] 8420#0: disable check peer: 192.168.179.100:8080
-
[root@www ~]# /usr/local/tomcat/bin/startup.sh
-
Using CATALINA_BASE: /usr/local/tomcat
-
Using CATALINA_HOME: /usr/local/tomcat
-
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
-
Using JRE_HOME: /usr/java/jdk1.8.0_131
-
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
-
Tomcat started.
-
-
-
2020/09/28 11:52:13 [error] 8420#0: check time out with peer: 192.168.179.100:8080
-
2020/09/28 11:52:17 [error] 8420#0: check time out with peer: 192.168.179.100:8080
-
2020/09/28 11:52:22 [error] 8420#0: check time out with peer: 192.168.179.100:8080
-
2020/09/28 11:52:26 [error] 8420#0: check time out with peer: 192.168.179.100:8080
-
2020/09/28 11:52:31 [error] 8420#0: check time out with peer: 192.168.179.100:8080
-
2020/09/28 11:52:35 [error] 8420#0: check time out with peer: 192.168.179.100:8080
-
2020/09/28 11:52:40 [error] 8420#0: check time out with peer: 192.168.179.100:8080
-
2020/09/28 11:52:44 [error] 8420#0: check time out with peer: 192.168.179.100:8080
-
2020/09/28 11:52:49 [error] 8420#0: check time out with peer: 192.168.179.100:8080
-
2020/09/28 11:52:53 [error] 8420#0: check time out with peer: 192.168.179.100:8080
-
2020/09/28 11:53:01 [error] 8420#0: enable check peer: 192.168.179.100:8080