backlog实际生效值为min(应用配置, net.core.somaxconn),若设16384但somaxconn为511,则真实队列长度仅511,超量连接在三次握手完成后被静默丢弃,导致客户端超时或Connection refused;须同步调大somaxconn并重启进程。

backlog参数实际生效值受系统somaxconn限制
设置 backlog 后连接仍被拒绝,大概率是系统级限制没跟上。Swoole 的 backlog 配置只是“申请值”,最终由内核参数 net.core.somaxconn 截断。比如你在代码里设了 'backlog' => 16384,但 cat /proc/sys/net/core/somaxconn 返回的是 511,那真实队列长度就是 511,多余连接会在三次握手完成后直接丢弃(不发 RST,客户端表现为超时或重传)。
必须同步调整系统参数:
- 临时生效:
echo 16384 > /proc/sys/net/core/somaxconn - 永久生效:在
/etc/sysctl.conf中添加net.core.somaxconn = 16384,再执行sysctl -p - 注意:修改后需重启 Swoole 进程,旧进程不会自动读取新值
backlog过小会导致SYN_RECV堆积和连接丢失
当并发连接突增(如秒杀、消息推送唤醒),若 backlog 太小,全连接队列迅速填满。此时新完成三次握手的连接无法入队,Linux 内核默认行为是静默丢弃——客户端收不到 ACK+SYN,重试几次后报 Connection timed out 或 ECONNREFUSED(取决于是否开启 tcp_abort_on_overflow)。
可观察到的现象包括:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
-
ss -lnt | grep :9501显示Recv-Q持续接近或等于 backlog 值 -
netstat -s | grep "listen overflows"计数持续上升 - 监控中新建连接成功率骤降,而 CPU/内存无明显压力
backlog不是越大越好,需匹配业务连接节奏
盲目设成 65535 并不推荐。过大的 backlog 会占用更多内核内存(每个连接在队列中至少保留部分 socket 结构),且在连接建立后未及时 accept() 时,会延长客户端感知延迟(排队等待时间变长)。
合理设定依据:
- 中等并发 API 服务(QPS 2k~5k):
backlog => 8192 - 长连接网关/IM(10w+ 在线):
backlog => 16384,并确保worker_num足够快地调用accept() - 若业务存在明显连接波峰(如整点推送),建议按峰值连接建立速率 × 平均处理延迟预估缓冲需求
与max_conn、ulimit -n 的关系容易混淆
backlog 控制的是「已握手但未 accept 的瞬时缓冲」,而 max_conn 是 Swoole 自身维护的「当前活跃连接总数上限」,ulimit -n 是「单进程能打开的文件描述符总数」。三者层级不同,但相互制约:
- 若
ulimit -n只有 1024,即使backlog设再大,也撑不住 1000 个连接同时接入(因为后续 accept 会失败) -
max_conn若设为 5000,但backlog只有 511,那么第 512~5000 个连接在建立瞬间就可能被丢弃,根本到不了计数逻辑 - 真正瓶颈往往出现在最低的那一环,排查时要逐层验证:
ulimit -n→somaxconn→backlog→max_conn
backlog 的数值意义只在连接洪峰到来的那几十毫秒内——它不提升吞吐,只防止第一道门被挤塌。真正决定你能撑住多少连接的,是 worker_num 处理速度、ulimit -n 上限,以及整个链路有没有阻塞点。


















