文档首页> IDC服务> 蓝易云:Nginx与Tomcat、Client请求配置问题

蓝易云:Nginx与Tomcat、Client请求配置问题

发布时间:2025-12-14 00:01       

蓝易云:Nginx 与 Tomcat、Client 之间长连接配置不一致怎么排 🚦

先把结论说在前面:
只要三段链路(Client ↔ Nginx ↔ Tomcat)的长连接策略不统一,你就会遇到这些经典问题:

  • 明明 QPS 不高,连接数却莫名飙升
  • 偶发 502、499、upstream prematurely closed connection
  • CPU、带宽看着都还行,用户就是感觉卡、偶发超时 😅

核心原因就是:谁先关、关多久、能复用几次,请求各方说的不一样。


一、长连接不一致本质是“超时与复用次数不统一”

三段配置分别控制了:

  • Client ↔ Nginx:
    • keepalive_timeoutkeepalive_requests
  • Nginx ↔ Tomcat(upstream):
    • proxy_http_versionproxy_set_header Connection
    • proxy_read_timeoutproxy_send_timeout
    • upstream keepalive
  • Tomcat 端 Connector(HTTP):
    • maxKeepAliveRequests
    • keepAliveTimeout
    • connectionTimeout

只要这几组参数的时间与次数跨度差太大,就容易:

  • Nginx 想复用连接,但后端已悄悄关掉
  • Client 坚信连接还活着,但 Nginx 已经超时关闭
  • 导致各种 RST、半连接、重试,业务层表现就是“偶发错误 + 体验发虚”。

二、几种典型错配场景与表现 💣

1. Client ↔ Nginx 超时不一致

场景:
Nginx keepalive_timeout 设得很小(例如 10s),而浏览器或 App 客户端会认为连接活得更久。

现象:

  • 用户短时间内连续多次请求,偶发 “连接被重置”、499
  • tcpdump 能看到:客户端还在复用旧连接发请求,服务端直接 RST

原因:
Nginx 在 10 秒后主动关闭空闲连接,客户端并不知道,只是还拿着旧连接发送下一次请求,于是撞上已关闭的 socket。


2. Nginx ↔ Tomcat 长连接策略不一致

如果:

  • Nginx 配置了 upstream <span style="color:red">keepalive</span>,想复用后端连接
  • 但 Tomcat 的 <span style="color:red">keepAliveTimeout</span> 比 Nginx 预期短,或 maxKeepAliveRequests 太小

就会出现:

  • Nginx 认为后端连接还能用,下一次请求复用
  • Tomcat 已经按自己规则把连接关了
  • Nginx 一发请求发现对面没了,日志报:
    <span style="color:red">upstream prematurely closed connection</span>,前端表现有时是 502/504

这种问题在高并发下放大非常明显:
连接反复建立/关闭,握手 + TLS 开销都会被放大,QPS 一上来就感觉“顶不住”。


三、Nginx 配置示例与逐行解释 🧩

1. Client ↔ Nginx 长连接建议

http {
    keepalive_timeout  65s;
    keepalive_requests 1000;
}

解释:

  • keepalive_timeout 65s;
    • 控制 客户端与 Nginx 空闲连接保活时间。
    • 建议不要设太小(如 5~10s),否则会频繁建立连接;
    • 60~75 秒通常比较均衡,既节省资源,又能较好复用。
  • keepalive_requests 1000;
    • 每个长连接最多承载多少个请求。
    • 设为 1000 表示同一条 TCP 连接最多被复用 1000 次;
    • 值太小会让连接频繁重建,太大在极端情况下少数连接承担海量请求,不利于负载均衡。

2. Nginx ↔ Tomcat upstream 长连接示例

upstream app_backend {
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    keepalive 100;
}

server {
    location / {
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_read_timeout 65s;
        proxy_send_timeout 65s;
        proxy_pass http://app_backend;
    }
}

逐行说明:

  • upstream app_backend { ... }
    • 定义名为 <span style="color:red">app_backend</span> 的上游集群。
  • server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    • 后端 Tomcat 节点地址。
    • max_fails:在 fail_timeout 时间窗内失败次数超过 3 次,就认为该节点暂时不可用。
    • 有助于自动摘除不稳定实例。
  • keepalive 100;
    • 表示 Nginx 会维护最多 100 条到该 upstream 的空闲长连接。
    • 这 100 条连接可在不同请求之间复用,减少握手消耗。
  • proxy_http_version 1.1;
    • 对后端使用 HTTP/1.1,前提条件是支持长连接复用。
    • 如果用 1.0 则默认倾向于短连接。
  • proxy_set_header Connection "";
    • 清理 Connection 头,让 Nginx 自己处理长连接复用逻辑;
    • 避免把客户端带来的 Connection: keep-alive/close 直接转发给后端导致混乱。
  • proxy_read_timeout 65s;
    • Nginx 等待后端响应数据的最大读超时。
    • 应与 Tomcat 的后台处理时间上限相协调,过短会在慢请求场景直接抛 504。
  • proxy_send_timeout 65s;
    • Nginx 向后端发送请求数据的最大写超时;
    • 用于防止网络异常或后端不读数据时一直卡住。
  • proxy_pass http://app_backend;
    • 把当前 location 下的请求转发给 app_backend 集群。

四、Tomcat 连接器长连接配置示例(HTTP)⚙️

server.xml 中典型配置:

<Connector
    port="8080"
    protocol="org.apache.coyote.http11.Http11NioProtocol"
    connectionTimeout="60000"
    maxKeepAliveRequests="1000"
    keepAliveTimeout="65000"
    maxConnections="10000"
/>

逐项说明: