[alibaba/tengine]dynamic_resolve 实现问题

2024-05-15 741 views
8
Question 1. 版本信息
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. 请求评论
  1. 请确认是否存在该问题
  2. 如果存在,如何规避该问题?

回答

9

你们这种用法不适合开健康检查,开了就会有这个问题。目前没想到啥太好的解决方式,最好是替换掉这种用DNS做负载均衡的方式,可以考虑用dyups试下ip的动态变更

1

@zhangxun94 谢谢答复。(1)我们已经在生产环境中使用 max_fails=0 关闭了 upstream server 被动健康检查 (2)dyups 我们先研究下,看看能不能用上。

5

@zhangxun94 谢谢答复。(1)我们已经在生产环境中使用 max_fails=0 关闭了 upstream server 被动健康检查 (2)dyups 我们先研究下,看看能不能用上。

你好,请问你们将max_fails置为0取消健康检查后,是否对线上业务有影响?

1

@zhangxun94 谢谢答复。(1)我们已经在生产环境中使用 max_fails=0 关闭了 upstream server 被动健康检查 (2)dyups 我们先研究下,看看能不能用上。

你好,请问你们将max_fails置为0取消健康检查后,是否对线上业务有影响?

因为我们还有主动健康机制,目前来看没什么影响。