
编者按
有很多客户问我们NGINX商业版与开源版本到底有什么区别,在官方网站有一个对比列表,但看完之后感觉好像还是没有get到其增强的精髓。为了更好的让大家了解NGINX Plus增强的能力及其应用场景,特编发《NGINX Plus增强能力系列专题》。本系列一共包含10篇内容,为了精简,我们没有包含那些显而易见的增强例如dashboard,而是更聚焦商业版本的关键能力与场景。本专题内容由数位专家参与。
NGINX Plus增强能力系列专题目录:
- 视频直播HLS与RTMP(☜)
- 代理缓存状态统计与清理(☜)
- 动态KV模块(☜)
- 动态KV模块(☜)
- NGINX实现动态黑白名单访问控制(☜)
- 主动健康检查
- NGINX集群
- JWT认证
- API接口
- 会话级log记录
- http_upstream与stream_upstream
- 下面我们就进入《NGINX Plus增强能力系列专题》的第五篇“主动健康检查”。1. ngx_http_upstream_hc_module模块介绍
被动健康检查
NGINX OSS和NGINX PLUS都支持被动健康检查(Passive health checks)
对于被动健康监测,一旦传输开始,NGINX 就会监控这个传输,并且会尝试恢复失败的连接。如果传输一直无法恢复,NGINX 会把服务器标记为不可用,并且在服务器被标记为可用之前向这台服务器停止发送请求。
主动健康检查(NGINX PLUS特有)
NGINX可以通过主动向每台服务器发送特殊的健康检查请求并检查响应来实现对 upstream 服务器的周期性的健康监测。
2. ngx_http_upstream_hc_module模块配置
要开启主动健康监测:使用 health_check 指令
在转发请求到 upstream 服务器组(proxy_pass)的 location 中使用 health_check 指令:

上面的配置定义了一个名为 backend 的 upstream 服务器组和一个虚拟服务器,还有一个将所有请求转发到 upstream 服务器组的 location。这还会使用默认参数打开高级健康监测:每 5 秒钟 NGINX 会发送一个请求到 backend 组中的每台服务器。如果发生任何通信错误或超时(或代理服务器返回 2XX 或 3XX 以外的状态码),服务器的健康检查失败,标记为异常服务器,NGINX 在这台服务器通过健康检查之前不会再发送客户端的请求到这台服务器。
zone 指令定义了一个在工作进程之间共享的内存区域,用来存储 upstream 服务器组的配置。这会使得工作进程可以使用相同的一组计数器来追踪从服务器组中的服务器的响应。zone 指令还可以动态配置组。
主动健康监测的默认参数可以用 health_check 指令的参数覆盖:

这里的 interval 参数把健康检查之间的延时增大为 10 秒(默认 5 秒)。fails 参数意味着服务器的健康检查失败三次后,被标记为不健康(高于默认值 1)。最后,passes 参数意味着服务器必须再次通过两次连续的检查(而不是默认值 1)。
指定请求 URI
使用 uri 参数设置健康检查中的请求要发送到哪个 URI:

指定的 URI 会添加到 upstream 块中的服务器的域名或 IP 地址之后。对于上面示例中的服务器组 backend 中的第一个服务器,健康检查会请求这个 URI:http://backend1.example.com/some/path。
定义自定义条件
最终,可以定义自定义条件,响应满足这些条件时才认为服务器通过了健康检查。条件定义在 match 块中,通过 health_check 指令中的 match 参数关联。

这个例子中,如果响应的状态码在 200 - 399 之间则通过健康检查,报文体不包含字符串维护模式(and its body does not contain the string maintenance mode)。
match 指令使 NGINX Plus 检查状态码、头字段和响应体。通过这个指令可以验证状态是否在指定范围内,响应是否包含一个头字段,头字段或响应体是否匹配一个正则表达式。match 指令可以包含一个 status 条件、一个 body 条件和多个 header 条件。只有在响应满足 match 块中为这台服务器定义的所有条件时,才认为通过健康检查。
例如,下面的 match 指令匹配响应码为 200 的状态码,头字段中的 Content-Type 必须为“text/html”,并且报文体中必须包含“Welcome to nginx!”:

下面的例子使用感叹号 ! 来定义要通过健康检查,响应不能匹配哪些条件。当状态码不是 301,302,303,307 且响应头字段不包含 Refresh 时,通过健康检查:

3. ngx_steam_upstream_hc_module模块介绍
被动健康检查
和http的健康检查一样,NGINX OSS和NGINX PLUS都支持被动健康检查(Passive health checks),原理也是一样的。如果一个连接到 upstream 服务器的尝试超时或失败,Nginx 会把服务器标记为 unavailable 并在指定的时间内停止向这台服务器发送请求。通过向 server 指令中添加下面的参数可以定义 Nginx 在哪些情况下认为服务器不可用
主动健康检查(NGINX PLUS特有)
NGINX可以通过主动向每台服务器发送特殊的健康检查请求并检查响应来实现对 upstream 服务器的周期性的健康监测。
NGINX Plus 向每台 upstream 服务器发送特殊的健康检查请求,并检查响应是否满足特定条件。如果一个到服务器的连接不能建立,则健康检查失败,并认为服务器故障。NGINX Plus 不会把客户端连接代理到故障服务器。如果服务器组定义了几个健康检查,任何一个健康检查失败都会使相关的服务器被视为故障。
4. ngx_steam_upstream_hc_module模块配置
指定共享内存区域

开启健康检查
在将连接代理到 upstream 服务器组的 server 上下文中添加 health_check
和 health_check_timeout
指令:

health_check 指令开启健康检查功能,health_check_timeout 指令在健康检查时覆盖 proxy_timeout 的值,因为健康检查的超时需要设置的很短。
微调TCP健康检查
默认情况下,Nginx Plus 会每隔 5 秒钟向 upstream 服务器组中的每台服务器发起一次连接尝试。如果连接无法建立,则 Nginx Plus 会认为健康检查失败,将对应的服务器标记为故障,并且停止将客户端连接发到这台服务器。
要改变默认行为,可以在 health_check 指令中包含下面的参数:
· interval – Nginx Plus 每隔多久发送一次健康检查(默认是 5 秒)
· passes – 服务器连续通过几次检查才能被视为健康(默认是 1 次)
· fails – 服务器连续几次检查失败才能被视为故障(默认是 1 次)

这个例子中,TCP 健康检查的间隔增大为 10 秒,服务器在 3 次连续的健康检查失败时被认为发生故障,并且服务器需要连续通过 2 次健康检查才被认为再次可用。
默认情况下,Nginx Plus 向 upstream 块中 server 指令指定的端口发送健康检查消息。可以指定另一个端口用于健康检查,这在同时监控一台主机上的多个服务时特别有用。通过 health_check
指令中的 port 参数可以覆盖默认端口:

match 配置块
可以配置一系列测试来验证服务器对健康检查的响应。这些测试定义在 stream 上下文中的 match 配置块中。指定 match 配置块时同时指定名字 tcp_test:

然后在 health_check
指令中通过 match 参数指明要使用哪个 match 块来验证响应:

成功运行健康检查的条件或测试,是用 set 和 send 参数设置的(The conditions or tests under which a health check succeeds are set with send and expect parameters):
·send – 要发送到服务器的文本字符串或十六进制文字(“/ x”后跟两个十六进制数字)。
· expect – 从服务器返回的数据需要匹配的字符串或正则表达式。
这两个参数可以有不同的组合,但是每次最多只能指定一个 send 和一个 expect:
·如果未指定 send 和 expect 参数,则只测试连接到服务器的能力。
·如果只指定了 expect 参数,则期望服务器会无条件发送数据:

·如果只指定了 send 参数,则期望连接会成功建立,并且指定的字符串会成功发送到服务器:

·如果同时指定 send 和 expect 参数,通过 send 参数从服务器获取的字符串必须匹配 expect 参数指定的正则表达式:

这个例子中,健康检查要通过,则 HTTP 请求一定要发送到服务器,并且从服务器返回的结果包含 200 OK 来指示这是一个成功的 HTTP 响应。
5. 场景使用
被动健康检查必须由业务流量出发,默认NGINX认为服务器是健康的,发送流量,当返回异常或者无响应时,NGINX会认为它已经down掉,并且设置一个停机时间,当超过停机时间,NGINX就会再次发送业务流量到这台服务器上,循环这个步骤。
显然被动健康检查对于业务的连续性是由一定的影响的,比如当服务器异常的时候,NGINX还是会将业务流量周期性的转发到服务器做尝试,而对于一些非常高的业务要求,显然是不够的。
6. 竞争分析
说到底,其实最重要的还是这部分,因为很多第三方版本已经自己开发了主动的健康检查,编译到NGINX OSS版本里面进行使用,这里我们就以最热门的Tengine为例。
ngx_http_upstream_check_module
该模块可以为Tengine提供主动式后端服务器健康检查的功能。
该模块在Tengine-1.4.0版本以前没有默认开启,它可以在配置编译选项的时候开启:./configure --with-http_upstream_check_module
Examples

指令
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
该指令可以打开后端服务器的健康检查功能。
指令后面的参数意义是:
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。7. 总结
1)NGINX OSS版本原生支持被动健康检查,也是最常用的一种健康检查,所以所有版本的NGINX都支持被动健康检查,并且功能相同。
2)主动健康检查只有NGINX PLUS才有,OSS版本必须加载第三方模块才能实现,如果使用NGINX PLUS和OSS原生版本对比,NGINX PLUS完胜!
NGINX PLUS支持的应用类别较多,包括HTTP、FastCGI、memcached、SCGI、uwsgi、TCP和UDP。
而Tengine只支持http相关的主动健康检查,并且可调参数较小。
