nginx -V
Tengine version: Tengine/2.3.2
nginx version: nginx/1.17.3
built by gcc 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)
built with OpenSSL 1.1.1c 28 May 2019
2. 问题描述
目前在我们的生产环境中使用 dynamic_resolve 配置指令,碰到一个使用问题。
示例配置如下:
upstream slupstream_6d7b779c-cb0d-4808-b33a-2acfd7c9b27e_2 {
dynamic_resolve fallback=stale fail_timeout=5s;
server a.test.com:80 weight=1;
keepalive 512;
keepalive_timeout 75;
}
server {
listen 0.0.0.0:9005 default_server backlog=65536 reuseport;
listen [::]:9005 default_server backlog=65536 reuseport;
resolver 172.17.0.2;
server_name _;
location / {
proxy_pass http://slupstream_6d7b779c-cb0d-4808-b33a-2acfd7c9b27e_2;
include proxy_params;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
......
}
根据 Nginx 的实现逻辑,虽然 upstream 块里只配置了一个 server,但是该 server 域名对应多个 IP 地址。在 Nginx 配置解析时,会根据 server 域名返回的多个 IP 地址,创建多个真实的 upstream server。
然后每次反向代理时,经过 ngx_http_upstream_dynamic_module 模块处理:
- 首先根据 RR 算法选择一个可用的 upsteam server
- 对该 server 的域名进行实时 DNS 解析,然后选择其中一个 IP 作为该 peer 的地址,建立连接
- 将返回结果记录到该 upsteam server 的状态里(fails 等状态信息)
如果 DNS 服务器针对域名返回了多个 IP 地址,而其中一个 IP 是故障服务器的 IP 地址。如果恰好选择了该故障 IP 地址,会导致本次连接失败,当前选择的 upstream server 就会认为不可用,需要等到 fail_timeout 之后才会重新选择该 server。此时 Nginx 会通过 ngx_http_upstream_next 选择下一个 upstream server。
如果该故障服务器 IP 没有及时剔除,每次选择的可用 upstream server 都有可能使用故障服务器 IP 地址。所以短时间内只要请求数量足够多,所有 upstream server 都会由于选择了故障 IP 地址而被标记为不可用,造成 Nginx 没有可用的 upstream server,直接输出 no live upstream ...
错误日志。且大概需要等待 fail_timeout 时间后,才会重新开始 try server。
这就造成一种现象:一个故障服务器的 IP 地址,导致所有 upstream server 都不可用,即使返回的其他 IP 地址都是可用的。
3. 请求评论- 请确认是否存在该问题
- 如果存在,如何规避该问题?