最近线上nginx经常把我的网关给踢掉,即流量不走网关,走backup了,特地本地测试了server不可用的情况,测试配置如下:
upstream test {
# simple round-robin
server 192.168.3.1:80 fail_timeout=180s;
server 192.168.3.2:80 fail_timeout=180s;
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
check_http_send "GET /healthcheck HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
Nginx 自己提供了被动的健康检查功能,即fail_timeout,默认10秒, 和 fail_nums认为1,即出现一次后端服务超时,nginx不会把请求发给这个upstream server。
我upstream server配置了2台机器,fail_timeout 为3分钟,fail_nums默认为1,其中一台出现read timeout时,
nginx 自动把超时的这个server标记为down不可用状态,但是过了一个heatcheck interval 后,我配置的是3秒,
这个健康检查肯定是成功的,但是这个被标记为down 的server并没有流量过来,只有过了3分钟流量才恢复,经过多次测试发现都是一样的结果。
这说明tengine的主动健康检查成功,但是nginx流量并没有打到这个机器上,通过分析代码和淘宝官方人的请教,终于知道原因,先贴下
代码,源码在:https://github.com/alibaba/tengine/blob/master/src/http/ngx_http_upstream_round_robin.c#L651
是nginx在路由时认为server不可用的关键地方
//这里是配置标记为down才为true
if (peer->down) {
continue;
}
//这里是tengine的healthcheck 检查,即健康检查为down时,就continue了,就不给这个机器打流量,
//如果healthcheck 成功,则继续下面的检查
#if (NGX_HTTP_UPSTREAM_CHECK)
if (ngx_http_upstream_check_peer_down(peer->check_index)) {
continue;
}
#endif
//nginx本身的被动检查,如果max_fails大于0,而且失败的次数大于max_fails就认为该server不可用,不可用的时间为fail_timeout。
if (peer->max_fails
&& peer->fails >= peer->max_fails
&& now - peer->checked <= peer->fail_timeout)
{
continue;
}
通过上面的代码,我们就可以解释为啥healthcheck检查成功了,但nginx还是没有给server打流量的原因了,因为tengine的健康检查代码
是加在max_fails和fail_timeout条件的前面,而且只有失败才不会去检查这个条件。
网友评论