要让 gin 应用通过 nginx 反向代理真正复用 tcp 连接,必须同时打通 client→nginx 和 nginx→gin 两条链路的长连接;client→nginx 段由 keepalive_timeout(建议 60–120s)和 keepalive_requests(按 qps×响应时间×1.5 计算,如 5000 qps×200ms≈1500–3000)控制,nginx→gin 段需在 upstream 块设 keepalive 32、location 中配 proxy_http_version 1.1 和 proxy_set_header connection "",且 gin 默认支持无需额外配置。

要让 Gin 应用通过 Nginx 反向代理真正复用 TCP 连接,必须同时打通 client→Nginx 和 Nginx→Gin 两条链路的长连接。只配一边,TIME_WAIT 会暴涨、延迟跳变、后端连接数虚高——这不是 Gin 或 Nginx 单方面的问题,而是配置断层导致的。
client 到 Nginx 的 keepalive 怎么设才不踩坑
这一段由 Nginx 主动管理,Gin 完全无感。关键不是“开没开”,而是参数是否匹配真实负载:
-
keepalive_timeout建议设为60s~120s:太短(如默认75s)会导致低频请求仍频繁重连;太长(如300s)可能让空闲连接被中间设备(如云厂商 SLB)静默回收 -
keepalive_requests必须调大:默认100在 QPS > 1000 场景下极易触发“刚复用几次就被强制断开”。建议按QPS × 平均响应时间(秒)× 1.5估算,例如 QPS=5000、平均耗时 200ms,可设为1500~3000 - 不用加
Connection: keep-aliveheader:HTTP/1.1 客户端(浏览器、curl、多数 SDK)默认携带,Nginx 自动识别并复用
Nginx → Gin 的 upstream keepalive 必须显式启用
Gin 默认支持 HTTP/1.1 和 Connection: keep-alive 响应头(无需额外配置),但 Nginx 默认用 HTTP/1.0 短连访问后端——这是最常漏掉的一环:
- 在
upstream块里加keepalive 32:表示每个 Nginx worker 进程最多缓存 32 个空闲连接到 Gin 后端。值不是越大越好,建议按(预估峰值并发 ÷ worker_processes) × 0.7计算,避免连接池积压 - 在
location块里必须配齐两行:proxy_http_version 1.1proxy_set_header Connection ""(注意是空字符串,不是"close"或"keep-alive") - 不要写
proxy_set_header Connection "keep-alive":这会让某些后端(包括部分 Gin 中间件)误判为客户端要求关闭连接
Gin 本身要不要做特殊处理
绝大多数情况下不需要。Gin 基于 net/http,而 Go 标准库从 1.0 起就默认支持 HTTP/1.1 长连接,且响应头自动包含 Connection: keep-alive(除非显式设置 w.Header().Set("Connection", "close")):
- 检查你的 Gin 中间件(如日志、认证)是否意外覆盖了
Connection头,可用curl -v http://localhost:8080确认响应头 - 如果 Gin 启用了
gin.Recovery()或自定义错误处理,确保 panic 恢复逻辑不干扰 header 写入 - Go 版本 ≥ 1.16 后,
http.Server的IdleTimeout默认为 0(不限制空闲时间),但 Gin 未暴露该字段;若需精细控制,应直接用http.Server启动,而非r.Run()
怎么验证长连接真的生效了
别只看配置文件是否 reload 成功,得看连接状态和响应行为:
- 执行
ss -tnp | grep :8080 | grep ESTAB | wc -l(假设 Gin 监听:8080):压测中该数值应稳定在upstream keepalive N设定值附近,而非随请求数线性增长 - 用
curl -H "Connection: keep-alive" -v http://your-nginx/发起多次请求,观察响应头是否始终含Keep-Alive: timeout=60, max=1500(对应你设的keepalive_timeout和keepalive_requests) - 重点盯住 Gin 日志里的连接数指标:如果每秒新建连接数 ≈ QPS,说明 upstream 长连接完全失效;理想情况是新建连接数趋近于 0
最容易被忽略的是 proxy_set_header Connection "" 这一行——少写、写错成变量或字符串都会让整个 upstream keepalive 归零。它不是“锦上添花”,而是开关级配置。











