蓝易云: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_timeout、keepalive_requests
- Nginx ↔ Tomcat(upstream):
proxy_http_version、proxy_set_header Connectionproxy_read_timeout、proxy_send_timeoutupstream keepalive
- Tomcat 端 Connector(HTTP):
maxKeepAliveRequestskeepAliveTimeoutconnectionTimeout
只要这几组参数的时间与次数跨度差太大,就容易:
- 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集群。
- 把当前 location 下的请求转发给
四、Tomcat 连接器长连接配置示例(HTTP)⚙️
server.xml 中典型配置:
<Connector
port="8080"
protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="60000"
maxKeepAliveRequests="1000"
keepAliveTimeout="65000"
maxConnections="10000"
/>
逐项说明:
connectionTimeout="60000"- 初始连接的握手/首包超时时间(毫秒),默认常见值为 60000。
- 太小会导致慢客户端直接被踢掉。
maxKeepAliveRequests="1000"- 每条长连接最多接收多少个 HTTP 请求。
- 建议与 Nginx 的
keepalive_requests大致对齐,避免一端 100 一端 1000。