前面已经介绍了Nginx负载均衡自带健康检测ngx_http_upstream_module和ngx_http_proxy_module模块,通过一定重试机制保证容错和负载均衡。使用真实的用户请求到后端节点出现故障时,才会切换到健康节点来提供访问,这样就会浪费一次转发,也会造成页面响应时间过久。严格来说,这自带模块不算是健康检查的功能。
由淘宝工程师姚伟斌大神开发的一个更专业的模块nginx_upstream_check_module,主动式后端服务器健康检查,通过它可以来检测后端的健康状态。如果后端不可用,则后面的请求就不会转发到该节点上。在淘宝自己 tengine 上也是自带了该模块,通过补丁方式添加该模块到nginx 中,下面部署流程!
安装nginx
yum -y install gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel wget
wget http://nginx.org/download/nginx-1.17.3.tar.gz
mkdir /usr/local/nginx
tar zxvf nginx-1.17.3.tar.gz
cd nginx-1.17.3
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-pcre
make && make install
测试启动/usr/local/nginx/sbin/nginx
安装 nginx_upstream_check_module模块
wget https://codeload.github.com/yaoweibin/nginx_upstream_check_module/zip/master
解压
unzip master && ll nginx_upstream_check_module-master
再次进入nginx的安装包位置
cd nginx-1.17.3
打补丁
patch -p1 < /root/nginx_upstream_check_module-master/check_1.16.1+.patch
./configure --prefix=/usr/local/nginx --add-module=/root/nginx_upstream_check_module-master/ --with-http_stub_status_module --with-http_ssl_module --with-pcre
make && make install (这模块加装方式会被覆盖,那根据nginx -V的信息,重装一次吧;也可以在nginx安装过程弄)
安装完毕,检测已安装模块
/usr/local/nginx/sbin/nginx -V
在nginx.conf配置文件里面的upstream加入健康检查,如下:
upstream name {
server 192.168.53.43:80;
server 192.168.53.44: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_send "GET /url/index.html HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx ;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://backend;
}
检测可视化,显示后端server池中server的健康状态,在nginx的配置server里加上一段,
location /nastatus {
check_status;
access_log off;
#allow 172.1.1.1;
#deny all;
}
测试访问http://IP/nastatus?format=json
有三种显示格式 考虑到获取健康检查后要对数据进行处理,所以选择json格式
format=html//默认显示的格式。
format=csv
format=json
如果可以访问成功则nginx健康检查模块配置成功。
用法:
check interval=milliseconds [fall=count] [rise=count] [timeout=milliseconds] [default_down=true|false] [type=tcp|http|ssl_hello|mysql|ajp] [port=check_port]
默认值是:interval=3000 fall=5 rise=2 timeout=1000 default_down=true type=tcp
interval:向后端发送的健康检查包的间隔(单位毫秒)。
fall(fall_count): 如果连续失败次数达到fall_count,服务器就被认为是down。
rise(rise_count): 如果连续成功次数达到rise_count,服务器就被认为是up。
timeout: 后端健康请求的超时时间。
default_down: 设定初始时服务器的状态,如果是true,就说明默认是down的,如果是false,就是up的。默认值是true,也就是一开始服务器认为是不可用,要等健康检查包达到一定成功次数以后才会被认为是健康的。
type:健康检查包的类型,现在支持以下多种类型
tcp:tcp连接检测端口通达并进入ESTABLISHED状态说明后端正常。
ssl_hello:发送一个初始的SSL hello包并接受服务器的SSL hello包。
http:发送HTTP请求,通过后端的回复包的状态来判断后端是否存活。
mysql: 向mysql服务器连接,通过接收服务器的greeting包来判断后端是否存活。
ajp:向后端发送AJP协议的Cping包,通过接收Cpong包来判断后端是否存活。
port: 健康检查请求发送端口,可以与后端服务器服务端口不同。
当type为 http,可使用check_http_send来配置http监控检查包发送的请求内容,
check_http_send "GET /url/index.html HTTP/1.0\r\n\r\n";
为了减少传输数据量,推荐采用 HEAD 方法。
check_http_send "HEAD / HTTP/1.0\r\n\r\n";
当采用长连接进行健康检查时,需在该指令中添加keep-alive请求头。
采用 GET 请求uri的size不宜过大,确保在1个interval内传输完成,否则判后端服务器或网络异常。
check_http_send "HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n";
指定HTTP回复的健康检查成功状态码,默认认为2XX和3XX的状态是健康的,但无法精确区分像301、302。
check_http_expect_alive [http_2xx | http_3xx | http_4xx | http_5xx]
采用type=tcp时
基于TCP三次握手,nginx服务器进入了ESTABLISHED状态后,当无新的请求来的空闲时,只要后端服务器不发送FIN四次挥手关闭连接来终止这TCP连接,那这后端一直都处于UP状态,(这种检测方式最节省资源,不用频繁探测,简单粗暴!)。但有个缺陷,当该后端死了而未在最后一口气发送FIN来终止(如直接断网或死机了)那后面的请求依然转发给该后端,浏览页面要等待一段时间回应了,像前面nginx自带检测模块一样,当nginx与后端在二层网络时,连续发4次ARP无回应,那放弃而重试其他后端;当内网三层转发的网络,如有其他网关代回应找不到此主机,那很快也会重试其他后端,要是真得不到回应,这浏览器等待为60s(而不是timeout值)后放弃而重试其他后端。
采用port=check_port时
当检测端口非后端服务器业务端口时,并default_down=true,rise值不为1时,会一直判断为down,(也是根据ESTABLISHED状态,也许因为不主动产生大于1的数量检测连接,所以判断为down)当default_down=false,rise值不为1时,可维持UP状态,当检测端口关闭,判down后,再次启动端口,已经无法再次被检测为健康了。
结尾!
项目地址:https://github.com/yaoweibin/nginx_upstream_check_module