首页/系统/Linux 内核与性能调优速查/net.core.somaxconn 全连接队列上限
sysctl 内核参数72 条

net.core.somaxconn 全连接队列上限

限制 listen 套接字 accept 队列的长度上限,实际生效值为 min(应用 backlog, somaxconn);高并发短连接服务的常见瓶颈点。

somaxconn 是什么

net.core.somaxconn 限制监听套接字上「已完成三次握手、等待应用 accept」的连接队列长度上限。应用调用 listen(backlog) 时申请的值会被内核截断为 min(应用 backlog, somaxconn),因此这个参数决定了全连接队列的物理天花板。旧内核默认 128,现代内核普遍是 4096。高并发短连接服务(Web 前端、API 网关、压测被打端)的偶发连接超时,往往就出在这里。

基本信息

参数net.core.somaxconn
作用对象全连接队列(已完成握手、待 accept)
常见默认值现代内核 4096,旧内核 128,以本机回读为准
实际生效值min(应用 listen backlog, somaxconn)
关联参数net.ipv4.tcp_max_syn_backlog 管半连接队列
生效条件修改后需监听进程重新 listen 才生效

典型使用场景

  • Web 前端与 API 网关:瞬时并发建连高峰时队列被瞬间填满,客端表现为连接超时
  • 被压测的服务端:压测机用大量短连接冲击时,先确认是全连接还是半连接队列溢出
  • Java/Nginx 等应用调大 backlog 后仍无改善:内核上限没跟着放开,需要同步提 somaxconn
  • 负载均衡后端的真实服务器:四层 LB 直连 RS,溢出会放大成首包超时
  • 排查偶发丢包与重传:连接层症状容易和网络丢包混淆,用队列计数器区分

查看与修改

查看与修改
sysctl net.core.somaxconn                 # 读当前上限
sysctl -w net.core.somaxconn=8192         # 临时调大
# 持久化:/etc/sysctl.d/99-net-tuning.conf 写 net.core.somaxconn = 8192
# 应用侧还需把 backlog 提到同一量级,如 nginx: listen 80 backlog=8192;
# 或 server 段配置 backlog=8192(不同版本指令位置不同,以官方文档为准)
systemctl restart nginx                   # 监听进程必须重启才用上新上限

验证队列与溢出

验证队列与溢出
ss -lnt | head                            # Listen 行的 Send-Q 即该监听套接字 backlog 上限
nstat -az TcpExtListenOverflows TcpExtListenDrops   # 队列溢出与丢弃计数
nstat -az TcpExtListenOverflows | tail -1 # 隔一段时间再读一次,看计数是否在增长
netstat -s | grep -i -E 'listen|overflow' # 无 nstat 时的替代查法

队列指标读法

指标含义异常信号
ss 的 Send-Q监听套接字的 backlog 上限远小于预期说明应用没接受新配置,或进程未重启
ss 的 Recv-Q当前堆积的已完成连接数持续贴近 Send-Q 说明 accept 速度跟不上
ListenOverflows全连接队列满导致的丢弃次数持续增长才是真溢出,偶发个位数可忽略
ListenDrops各类监听丢包总计数比 Overflows 大得多时同时看半连接与内存因素
改大 somaxconn 只是抬高上限,不改应用行为:listen backlog 仍取两者中的较小值。只改内核参数不调应用 backlog,通常是一条无效变更;反过来只调应用 backlog 而内核上限很小,也一样被截断。
队列溢出且应用 accept 不及时,症状是客户端偶发连接超时但服务端日志里看不到任何请求。排查顺序建议是:先看 nstat 的 ListenOverflows 是否增长,再用 ss -lnt 核对实际队列长度,最后才决定调参数还是优化应用的 accept 循环。
现代内核的 tcp_abort_on_overflow 决定溢出后的处理方式:默认丢弃握手让客户端重传(表现为延迟上升),置 1 则回 RST 让客户端立刻失败。生产上一般保持默认,把溢出计数作为容量告警而非靠 RST 暴露问题。
全连接队列与半连接队列是两套独立结构:前者由 somaxconn 与应用的 listen backlog 决定,后者由 tcp_max_syn_backlog 决定。客户端只发出 SYN、握手尚未完成时堆积在半连接队列,此时调 somaxconn 没有意义;握手已完成却没人 accept,才是全连接队列的问题。

易错点

  • 只改 somaxconn 不改应用 backlog:实际生效值仍取较小的一方,改完毫无变化还以为内核不生效
  • 改完不重启监听进程:已经 listen 的套接字仍沿用旧上限,必须重启或重建监听才生效
  • 把偶发连接超时直接归因于队列:先用 nstat 看 ListenOverflows 是否持续增长,网络丢包与后端慢也会造成同样症状
  • 看到 ss 的 Recv-Q 不为 0 就断定溢出:少量堆积是正常过渡态,要看是否持续贴近 Send-Q 并伴随丢弃计数
  • 把 backlog 一次性调到几十万:队列本身不耗太多内存,但过深的排队会把超时问题推后暴露,掩盖真正的处理能力瓶颈

数据来源与参考

  • Linux 内核 Documentation/admin-guide/sysctl/net.rst
  • man 7 tcp(listen backlog 语义)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌