实战排查生产环境 Nginx upstream timed out (110) 偶发 504 与长连接调优

举报
yd_260072176 发表于 2026/11/09 07:44:40 2026/11/09
【摘要】 一、生产环境故障背景与现象分析在微服务架构或典型的前后端分离部署中,Nginx 作为入口网关承担着反向代理、负载均衡和 SSL 卸载等核心职责。在日常高并发或大促流量激增场景下,运维团队经常会收到告警系统派发的 HTTP 504 Gateway Time-out 报警,查看 Nginx 的 error.log,通常会伴随如下典型错误:2026/11/09 07:15:22 [error] 1...

一、生产环境故障背景与现象分析

在微服务架构或典型的前后端分离部署中,Nginx 作为入口网关承担着反向代理、负载均衡和 SSL 卸载等核心职责。在日常高并发或大促流量激增场景下,运维团队经常会收到告警系统派发的 HTTP 504 Gateway Time-out 报警,查看 Nginx 的 error.log,通常会伴随如下典型错误:

2026/11/09 07:15:22 [error] 14829#14829: *894102 upstream timed out (110: Connection timed out) while connecting to upstream, client: 192.168.10.45, server: api.internal.cloud, request: "GET /api/v1/order/query HTTP/1.1", upstream: "http://10.244.3.18:8080/api/v1/order/query", host: "api.internal.cloud"

与常见的业务处理超时(如慢 SQL 或外部依赖阻塞导致的响应读取超时 upstream timed out while reading response header from upstream)不同,这里的错误明确指出了阶段:while connecting to upstream,错误码是操作系统的 110 (ETIMEDOUT)。

这意味着 Nginx 在尝试与后端 Upstream 节点发起 TCP 三次握手时,发送了 SYN 包却在设定的超时时间(默认 proxy_connect_timeout 60s;)内未收到后端的 SYN+ACK,或者在重试多次后操作系统直接返回连接超时。

二、深层根因探究:为什么在连接建立阶段超时?

在排查 Linux 生产环境下的连接超时时,必须深入到 TCP/IP 协议栈与内核参数层面。通过线上抓包(tcpdump)与内核套接字分析(ss -lnt),主要根因可归纳为以下几类:

  1. 后端服务器半连接队列(SYN Backlog)或全连接队列(Accept Queue)溢出:当后端服务短时间内涌入大量短连接建连请求,若后端应用的 somaxconn 或 backlog 较小,或者 Worker 线程被慢请求占满未能及时调用 accept(),全连接队列会被迅速填满。此时 Linux 内核默认行为是直接静默丢弃后续到达的 SYN 握手包(防 SYN 洪水并期望客户端指数退避重试),导致 Nginx 端发生建连超时。
  2. 短连接风暴导致 TIME_WAIT 耗尽与端口复用冲突:Nginx 默认配置对 Upstream 使用 HTTP/1.0 且不保持长连接(即每个请求都新建 TCP 连接并随即断开)。高 QPS 下,每秒会产生数万个短暂的 TCP 连接。即使开启了 net.ipv4.tcp_tw_reuse,如果中间经过 NAT 网关且开启了 tcp_tw_recycle(或 PAWS 时间戳校验冲突),会导致来自同一 IP 的新 SYN 包被后端静默丢弃。
  3. 云环境 Pod 弹性扩缩容或 DNS 缓存陈旧:在容器编排或微服务集群中,后端 Pod 销毁后,若 Nginx 内部仍缓存了失效的旧 IP,发往已不存在主机的 SYN 包由于无法收到任何响应(或黑洞路由),必然会持续等待直至 proxy_connect_timeout 耗尽。

三、基于 Upstream Keepalive 连接池的深度调优实战

针对短连接风暴与建连耗时问题,最根本且高效的解决方案是在 Nginx 与后端服务之间引入 HTTP 长连接池,复用已建立的 TCP 链路,彻底消除握手开销。

1. 配置 Nginx Upstream Keepalive 指令

在 Nginx 配置文件中,仅仅在 upstream 块里写 keepalive 是不够的,必须同时在 location 块中将 HTTP 协议版本升级为 1.1 并清空 Connection 头部:

upstream backend_cluster {
    server 10.244.3.18:8080 max_fails=3 fail_timeout=10s;
    server 10.244.3.19:8080 max_fails=3 fail_timeout=10s;

    # 每个 Nginx worker 进程保留的空闲长连接最大数量
    keepalive 256;
    # 允许复用的最大请求数,防止内存泄漏或连接老化
    keepalive_requests 50000;
    # 空闲连接保持时长
    keepalive_timeout 65s;
}

server {
    listen 80;
    server_name api.internal.cloud;

    location /api/ {
        proxy_pass http://backend_cluster;

        # 必须显式指定 HTTP/1.1,默认 1.0 不支持长连接
        proxy_http_version 1.1;
        # 清除 Connection 头部以启用长连接(默认 Nginx 会将其设为 close)
        proxy_set_header Connection "";

        # 优化超时时间:连接超时不宜设得过长,生产环境建议 3s~5s 以便快速失败重试
        proxy_connect_timeout 3s;
        proxy_read_timeout 30s;
        proxy_send_timeout 15s;

        # 允许在遇到连接超时或错误时,快速将请求转移到下一台健康后端
        proxy_next_upstream error timeout invalid_header http_502 http_503 http_504;
        proxy_next_upstream_tries 3;
        proxy_next_upstream_timeout 10s;

        # 传递客户端真实信息
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

2. 内核连接队列参数协同优化

为了配合长连接池并彻底解决突发流量下的连接堆积,后端宿主机与容器节点的内核参数需同步调整:

# 查看当前系统的全局最大监听队列限制
sysctl net.core.somaxconn
# 提高全连接队列上限(建议生产环境调整至 4096 或更高)
sudo sysctl -w net.core.somaxconn=8192

# 调大半连接 SYN 队列容量
sudo sysctl -w net.ipv4.tcp_max_syn_backlog=8192

# 启用安全重用 TIME_WAIT 套接字(仅适用于出站客户端连接)
sudo sysctl -w net.ipv4.tcp_tw_reuse=1

# 调大系统可分配的本地临时端口范围
sudo sysctl -w net.ipv4.ip_local_port_range="10240 65535"

四、调优效果验证与监控指标观察

完成上述长连接配置与参数调优后,通过 nginx -s reload 进行平滑热重载,并通过以下手段进行生产压测验证:

  1. TCP 连接状态监控:在 Nginx 节点执行 ss -ant | awk '{print $1}' | sort | uniq -c,观察到原先大量处于 TIME_WAIT 的连接数从数万级别急剧下降至数百个,而 ESTABLISHED 状态的连接保持平稳复用。
  2. 504 错误率清零:在 Grafana 监控大盘上,Nginx 的 Upstream 请求响应耗时 P99 显著降低(由于免去了每次建连的 1 个 RTT 延迟),upstream_connect_time 维持在 0.000~0.001 秒区间,偶发性的 504 错误彻底绝迹。
  3. 后端负载明显减轻:后端 Web 容器(如 Tomcat/Gunicorn)无需频繁分配与销毁 Socket 句柄,CPU 软中断(si)占比下降约 30%,整体集群吞吐量得到质的飞跃。

总结:生产环境中排查网关层与后端交互的超时异常,必须精准区分“连接超时”与“读写超时”。针对 while connecting to upstream,优先建立 HTTP/1.1 Keepalive 长连接池并压低 proxy_connect_timeout 结合快速失败重试,是保障高可用与低延迟的最优雅架构实践。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。