关键在于提升内核全连接队列(ACCEPT队列)容量以应对突发连接,其上限由listen()的backlog参数与net.core.somaxconn的较小值决定;需同步调优半连接队列(tcp_max_syn_backlog)、事件循环accept效率及网卡接收队列(netdev_max_backlog)。
关键在于让内核的全连接队列(ACCEPT队列)能承接住突发的已完成握手连接,避免应用层事件循环来不及调用
时连接被丢弃。backlog 参数本身不直接控制性能,而是它与内核参数共同决定了这个“缓冲能力”的上限。
理解 listen 的 backlog 实际生效逻辑
应用调用
时传入的值,并不会直接成为队列长度。内核会取该值与系统参数
的较小者作为最终的 ACCEPT 队列最大长度。也就是说,即使你在代码里写了
,如果
是默认的 128,那队列实际最多只能存 128 个已建立连接。
检查当前限制:
临时调整:
永久生效:在
中添加
,然后运行
同步调优半连接队列,防止握手卡在第一步
如果大量客户端同时发起连接,SYN 包会先涌入半连接队列(SYN 队列)。若此队列溢出,客户端根本收不到 SYN+ACK,三次握手连第一步都失败,事件循环再快也无从处理。
查看当前值:
建议设为与
同量级或略高,例如
注意:该参数需配合启用
作为兜底,防止 SYN Flood 导致服务不可用
确保事件循环自身不成为瓶颈
内核队列只是缓冲区,最终仍需事件循环(如 epoll、kqueue)及时调用
将连接从队列中取出。如果单次循环只 accept 一个连接,而并发连接数远超此速度,队列很快又会积压。
在事件就绪后,应循环调用
直到返回
或
,一次性清空当前就绪的连接
避免在
后立即进行耗时操作(如数据库连接、复杂鉴权),应尽快交由工作线程或协程处理,保持事件循环轻量
监控
输出中的
(已建立连接数)与
(半连接数)比例,若
持续高位且增长缓慢,说明事件循环消费太慢
补充:网络层接收能力也要匹配
当网卡收到海量数据包,它们会先排队进入内核的软中断处理队列。如果这个队列(
)太小,包会在驱动层就被丢弃,连接请求甚至无法抵达 TCP 协议栈。
万兆网或高吞吐场景下,建议将该值提升至
或更高
调整后可通过
观察是否有输入错误上升
accept()listen(fd, backlog)net.core.somaxconnlisten(sockfd, 65535)somaxconnsysctl net.core.somaxconnecho 4096 | sudo tee /proc/sys/net/core/somaxconn/etc/sysctl.confnet.core.somaxconn = 4096sysctl -psysctl net.ipv4.tcp_max_syn_backlogsomaxconn8192tcp_syncookies=1accept()accept()EAGAINEWOULDBLOCKaccept()ss -sestabsynrecvestabnet.core.netdev_max_backlog16384cat /proc/net/snmp | grep -i "InErrs\|OutErrs"