一、引言:别让 Nginx 成为"短连接制造机"
当 Nginx 作为反向代理时,它位于客户端和后端应用服务器(如 Tomcat, Node.js, PHP-FPM)之间。一个常见的性能陷阱是:Nginx 与后端服务器之间的连接默认是短连接!
这意味着,对于每一个来自客户端的请求,Nginx 都会:
- 与后端服务器进行一次完整的 TCP 三次握手。
- 转发请求并接收响应。
- 立即进行 TCP 四次挥手 关闭连接。
而后端服务器处理 TCP 连接的开销通常远大于 Nginx。在高并发场景下,这种"用完即弃"的模式会导致:
- 后端服务器 CPU 飙升:大量时间花在处理连接建立/关闭上。
- Nginx 本地端口耗尽 :产生海量
TIME_WAIT连接。 - 整体吞吐量急剧下降。
upstream keepalive 机制正是为解决此问题而生。它允许 Nginx 与后端服务器之间复用 TCP 连接,将 Nginx 从"短连接制造机"转变为高效的"连接管理者"。
💡 核心价值 :
正确配置
upstream keepalive,是释放 Nginx 反向代理全部性能潜力的关键一步,能带来数倍的 QPS 提升!
二、工作原理:Nginx 的上游连接池
upstream keepalive 并非简单地开启一个开关,而是建立了一个智能的连接池。
1. 核心流程
- 请求到来:Nginx 收到一个需要转发给后端的请求。
- 池中寻觅 :Nginx 检查其
upstream连接池,看是否有空闲的、指向目标后端的 KeepAlive 连接。 - 复用 or 新建 :
- 如果有空闲连接,则直接复用,发送请求。
- 如果没有,则新建一个 TCP 连接。
- 归还连接 :请求处理完毕后,如果后端响应支持 KeepAlive,Nginx 不会关闭 这个连接,而是将其放回连接池,供后续请求使用。
- 池满或超时:当连接池已满,或者连接空闲时间过长,Nginx 会清理掉这些连接以释放资源。
2. 关键特性
- 每个 Worker 独立 :连接池是按 Nginx 的
worker进程隔离的。总的最大空闲连接数 =keepalive*worker_processes。 - 仅缓存空闲连接 :
keepalive指令定义的是空闲连接的数量上限,而不是总连接数。活跃的连接不受此限制。
三、核心配置:三步开启上游 KeepAlive
要让 upstream keepalive 生效,必须同时配置以下三个部分,缺一不可。
第一步:在 upstream 块中定义连接池大小
upstream backend {
# 为每个 worker 进程缓存 32 个空闲的 keepalive 连接
keepalive 32;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}
keepalive 32: 这是最核心的指令。数字32表示每个worker进程最多可以缓存 32 个空闲的、与后端服务器的 HTTP/1.1 KeepAlive 连接。
第二步:在 location 块中强制使用 HTTP/1.1
server {
location / {
proxy_pass http://backend;
# 必须设置!强制 Nginx 使用 HTTP/1.1 与后端通信
proxy_http_version 1.1;
}
}
proxy_http_version 1.1: KeepAlive 是 HTTP/1.1 的默认行为。如果不显式指定,Nginx 默认使用 HTTP/1.0 与后端通信,而 HTTP/1.0 默认是短连接。
第三步:清除干扰性的 Connection 头
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
# 必须设置!清除从客户端带来的 Connection 头
proxy_set_header Connection "";
}
}
proxy_set_header Connection "": 客户端可能会发送Connection: close或Connection: keep-alive。如果不清理,这个头部会被透传给后端,可能干扰 Nginx 与后端之间 KeepAlive 连接的建立。将其设为空字符串,可以确保 Nginx 完全掌控与后端的连接行为。
四、深度调优:如何确定 keepalive 的最佳值?
keepalive 的值并非越大越好,需要根据业务场景精确计算。
1. 计算公式
一个经验公式是:
每个后端所需连接数 ≈ (QPS / 后端数量) * 平均响应时间(秒)
2. 实战案例
假设你的系统指标如下:
- 总 QPS: 2000
- 后端服务器数量: 4 台
- 平均响应时间(RT): 50ms (0.05秒)
计算过程:
- 每台后端承受的 QPS =
2000 / 4 = 500 - 每台后端所需的连接数 =
500 * 0.05 = 25
因此,keepalive 的值应略大于 25,比如设置为 32。
3. 监控与验证
- 监控
TIME_WAIT: 使用ss -tan state time-wait | wc -l命令。配置生效后,TIME_WAIT连接数应大幅下降。 - 观察后端负载: 后端服务器的 CPU 使用率(特别是 system CPU)应该显著降低。
- 压测对比 : 使用
wrk或ab工具进行压测,对比开启前后的 QPS 和延迟。
五、常见陷阱与避坑指南
1. 只配了 upstream keepalive,忘了 proxy_http_version
这是最常见的错误。结果是,Nginx 依然使用 HTTP/1.0 与后端通信,keepalive 指令完全失效。
2. 后端服务器不支持 KeepAlive
确保你的后端应用(如 Tomcat)也配置了合理的 keepAliveTimeout 和 maxKeepAliveRequests。如果后端主动关闭连接,Nginx 的连接池就失去了意义。
3. 连接池大小不足
如果 keepalive 值设置过小,在高并发下,连接池会频繁地创建和销毁连接,无法达到复用的效果,性能提升有限。
4. 与 proxy_next_upstream 的交互
当 proxy_next_upstream 触发重试时,Nginx 会关闭当前连接并尝试下一个服务器。这属于正常行为,但需注意它会影响连接池的利用率。
六、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!