You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Nginx SNI Docker Swarm环境下后端服务无法重新解析问题

解决Nginx基于主机名的TCP转发上游重启后无法重新解析的问题

我来帮你排查这个Nginx TCP转发的DNS解析问题——这种上游容器重启后无法重新解析的情况,我之前也遇到过几次,主要是因为Nginx在stream模块下的DNS缓存和连接复用逻辑和http模块有点不一样,咱们一步步来解决:

1. 检查Resolver的配置位置与参数

你当前把resolver放在server块里虽然可行,但更建议放在stream全局块中,确保所有TCP转发服务都能复用这个DNS配置。另外,需要补充ipv6=off参数(如果你的上游没有IPv6服务),避免Nginx解析到无效的IPv6地址导致连接失败:

stream {
    # 使用公共DNS或你的内部DNS服务器,valid=30s确保缓存30秒后重新解析
    resolver 8.8.8.8 valid=30s ipv6=off;

    server {
        listen 443;
        ssl_preread on;
        # 确保$name是从SNI正确获取的上游主机名
        set $name $ssl_preread_server_name;
        proxy_pass $name:443;
    }
}

注意:必须通过变量(比如$name)传递上游地址,Nginx才会在每次请求时触发DNS重新解析;如果直接写固定域名,Nginx只会在启动时解析一次。

2. 调整连接超时与复用设置

上游容器重启后,Nginx可能还在复用之前建立的长连接,导致连接拒绝错误。你需要添加连接超时配置,并禁用不必要的长连接:

server {
    listen 443;
    ssl_preread on;
    set $name $ssl_preread_server_name;
    proxy_pass $name:443;

    # 缩短连接超时,让Nginx更快发现连接失败并触发重新解析
    proxy_connect_timeout 5s;
    # 设置整体请求超时
    proxy_timeout 30s;
    # 禁用HTTP长连接,避免复用失效的连接(如果上游是HTTP服务)
    proxy_http_version 1.1;
    proxy_set_header Connection "";
}

3. 验证DNS解析有效性

在Nginx服务器上手动执行DNS解析,确认上游容器重启后,DNS服务器能返回新的IP地址:

dig your-upstream-domain.com
nslookup your-upstream-domain.com

如果DNS解析正常,但Nginx还是用旧IP,可能是Nginx的DNS缓存没有正确刷新——你可以尝试发送USR1信号让Nginx重新加载配置并刷新缓存:

nginx -s reload
# 或者强制刷新缓存
kill -USR1 $(cat /var/run/nginx.pid)

4. 检查Nginx版本兼容性

部分旧版本的Nginx(比如低于1.19.0)在stream模块的DNS动态解析上存在bug,建议升级到最新的稳定版(比如1.24.x系列),很多这类解析问题在新版本中已经被修复。

最后验证

上游容器重启后,等待30秒(你的valid配置时间),然后测试连接。如果还是有问题,可以查看Nginx的错误日志(通常在/var/log/nginx/error.log),看是否有更详细的DNS解析错误信息,方便进一步排查。

内容的提问来源于stack exchange,提问作者thewire247

火山引擎 最新活动