温馨提示×

怎么理解Linux backlog

小樊
64
2026-08-17 08:50:10
栏目: 智能运维

在 Linux 网络编程里,backlog 通常出现在 listen(int sockfd, int backlog) 这个系统调用中,用来控制 TCP 连接请求队列的大小。理解它需要结合 TCP 三次握手和内核实现来看。


一、从 listen() 说起

int listen(int sockfd, int backlog);

它的作用是:

把 socket 从主动 socket 变成 被动 socket,开始接受连接请求。

backlog 的含义是:内核为这个 socket 维护的“半连接 + 全连接队列”的最大长度之一。


二、TCP 连接建立与两个队列

TCP 建立连接是三次握手:

客户端       服务器
  |  SYN  -->   |
  |  <-- SYN+ACK|
  |  ACK  -->   |

在服务器端,内核在三次握手过程中会维护 两个队列:

1️⃣ 半连接队列(SYN Queue)

  • 存放 已收到 SYN,但还没完成三次握手 的连接
  • 属于 半开连接(half-open)
  • 对应 TCP 状态:SYN_RECV

2️⃣ 全连接队列(Accept Queue)

  • 存放 三次握手已经完成,但应用还没调用 accept() 取走 的连接
  • 对应 TCP 状态:ESTABLISHED

三、backlog 到底控制哪个队列?

✅ 现代 Linux(kernel ≥ 2.2)

backlog 主要限制的是:全连接队列(Accept Queue)的最大长度

backlog = 全连接队列的最大长度

半连接队列的长度 不完全由 backlog 控制,而是受另一个参数影响。


四、相关内核参数

1️⃣ 全连接队列

cat /proc/sys/net/core/somaxconn
  • 默认值通常是 4096
  • backlog 的实际生效值 = min(backlog, somaxconn)

✅ 即使你写:

listen(fd, 100000);

如果 somaxconn = 4096,实际也只生效 4096。


2️⃣ 半连接队列

半连接队列大小受:

cat /proc/sys/net/ipv4/tcp_max_syn_backlog

影响,例如:

net.ipv4.tcp_max_syn_backlog = 8192

✅ 半连接队列 ≈ tcp_max_syn_backlog


五、队列满了会发生什么?

全连接队列满

  • 新的已完成三次握手的连接:
    • 可能被丢弃
    • 或发送 RST
  • 客户端可能看到 connection reset 或超时

半连接队列满

  • 新 SYN 被丢弃
  • 客户端表现为超时重传

六、backlog 设置多大合适?

经验建议

场景 建议
普通 Web 服务 1024 ~ 4096
高并发服务 8192 或更高
同时调大 somaxconn + tcp_max_syn_backlog

示例

sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.tcp_max_syn_backlog=65535
listen(fd, 65535);

七、常见误区

❌ backlog = 最大并发连接数
✅ 它只是 等待 accept 的连接数

❌ backlog 越大越好
✅ 太大浪费内核资源,且受系统参数限制

❌ 半连接队列由 backlog 决定
✅ 现代 Linux 不是


八、一句话总结

Linux 中的 backlog 是 listen() 用来限制“已完成三次握手、但应用尚未 accept 的连接队列”大小的上限,实际值受 somaxconn 限制;半连接队列由 tcp_max_syn_backlog 控制。

如果你愿意,我也可以结合 源码(tcp_v4_syn_recv_sock / inet_csk_reqsk_queue) 或 抓包示例 帮你更深入理解。

0 踩