backlog参数只控制已完成三次握手但未被accept()处理的连接暂存数量,不缩短单个连接处理时间;其实际值取应用设置与net.core.somaxconn的较小者,溢出会导致连接拒绝而非延迟。

backlog 参数本身不解决“排队延迟”,它只决定连接建立阶段能暂存多少已完成三次握手、但尚未被应用层 accept() 的连接。真正影响连接建立快慢的,是这个队列是否溢出——溢出就会丢包或拒绝新连接,用户感知为“连不上”或“超时”,而不是“等得久”。所以调优 backlog 的目标是:让合法连接不被丢弃,而非缩短单个连接的处理时间。
先分清是哪类排队
高并发下出现连接问题,常见两类排队,机制和对策完全不同:
-
半连接队列(SYN Queue)排队:客户端发了 SYN,服务端还没回复 SYN+ACK。表现为大量
SYN_RECV状态连接,错误日志里常有 “connection timeout” 或客户端重试。主因是tcp_max_syn_backlog过小或遭遇 SYN Flood(此时应开tcp_syncookies)。 -
全连接队列(ACCEPT Queue)排队:三次握手已完成,连接在内核里等着被应用
accept()。这就是 backlog 控制的队列。表现为ss -ltn输出中监听端口的Recv-Q持续接近Send-Q,客户端报 “Connection refused” 或 “Cannot assign requested address”。主因是应用 accept 速度跟不上建连速度,或somaxconn/ 应用 backlog 设置过低。
backlog 实际生效值怎么算
你代码或配置里写的 backlog 值,未必就是最终起作用的长度。Linux 内核取两者最小值:
- 应用层设置值(如 Nginx 的
listen 80 backlog=2048,Puma 的?backlog=2048,MySQL 的back_log=1000) - 系统全局上限
net.core.somaxconn(默认通常 128 或 512)
执行 sysctl net.core.somaxconn 查当前值;若它小于你的应用设置,调大它才有效。改完需重启服务(如 Nginx、Puma)或 MySQL(back_log 不支持热更新)。
合理设置 backlog 的参考方法
没有放之四海而皆准的数字,但可按场景估算:
- 普通 Web 服务(Nginx/PHP-FPM):1024~2048 足够;压测中若
ss -ltn显示Recv-Q频繁打满,就逐步加到 4096 - 短连接高频服务(如 API 网关):建议设为峰值 QPS × 平均连接建立耗时(秒)。例如峰值 5000 QPS、平均建连 20ms,则 backlog ≈ 5000 × 0.02 = 100
- Kubernetes 环境:每个 Pod 独立队列。4 个 Pod 各配 1024,比 1 个 Pod 配 4096 更能分散排队压力
- 避免盲目拉高:超过 8192 后收益递减,且可能触发内核丢包(尤其云主机),需同步检查
tcp_abort_on_overflow是否为 0
光调 backlog 不够,还得看配套
如果 backlog 已调大,但仍有连接失败,说明瓶颈不在队列长度,而在其他环节:
- 检查
ss -s输出中的skipped或overflow计数,确认是否真有队列溢出 - 观察应用线程/Worker 是否饱和(如 Puma 的
workers数、Nginx 的worker_connections) - 确认文件描述符限制:
ulimit -n和/proc/sys/fs/file-max是否足够 - 排查网络层:客户端是否受本地端口耗尽(
TIME_WAIT太多)、中间 LB 重置连接等影响










