温馨提示×

linux backlog和tcp关系

小樊
43
2026-09-29 12:54:46
栏目: 智能运维

在 Linux 网络编程和内核网络中,backlog 和 TCP 有紧密关系,主要体现在 TCP 连接建立过程(三次握手) 以及 内核中两个队列的管理 上。

下面从概念到内核实现逐步说明。


1. 什么是 backlog

在 Linux 中,backlog 通常出现在:

listen(sockfd, backlog);

作用:
告诉内核,该 socket 能够容纳的“等待被 accept 的 TCP 连接”的最大数量(近似含义)。

但需要注意:

backlog 并不等于“最大并发连接数”,也不等于“已完成连接数 + 半连接数”的精确值。


2. TCP 三次握手与 backlog 的关系

TCP 建立连接的过程:

  1. 客户端发送 SYN
  2. 服务端回复 SYN+ACK
    • 此时连接进入 半连接状态
  3. 客户端发送 ACK
    • 连接进入 全连接状态(已完成连接)

Linux 内核为此维护了两个队列:

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

  • 存放:已收到 SYN,但未完成三次握手的连接
  • 对应 TCP 状态:SYN_RCVD
  • 受以下参数影响:
    • net.ipv4.tcp_max_syn_backlog
    • backlog(间接)

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

  • 存放:三次握手已完成,但应用层还没调用 accept() 的连接
  • 对应 TCP 状态:ESTABLISHED
  • 长度受 listen(backlog) 限制

3. backlog 实际控制的是什么

在 现代 Linux 内核(2.2+) 中:

min(backlog, somaxconn)

决定的是 全连接队列(Accept Queue)的最大长度。

  • somaxconn:
    cat /proc/sys/net/core/somaxconn
    
    默认通常是 128 或 4096

例如:

listen(sockfd, 1000);

如果 somaxconn = 128,实际队列长度 ≈ 128。


4. 半连接队列和 backlog 的关系

虽然 listen(backlog) 主要控制 全连接队列,但:

  • 当 全连接队列满 时:
    • 内核可能 丢弃或延迟 ACK
  • 当 半连接队列满 时:
    • 新的 SYN 被丢弃(或触发 SYN Cookie)

相关参数:

net.ipv4.tcp_max_syn_backlog
net.ipv4.tcp_syncookies

5. backlog 满了会发生什么

全连接队列满

  • 已完成握手的连接 无法进入 accept 队列
  • 客户端可能表现为:
    • 连接超时
    • 重试
  • 服务端:accept() 阻塞或无新连接

半连接队列满

  • 新 SYN 被丢弃
  • 若开启 tcp_syncookies:
    • 不丢 SYN,而是用 cookie 验证

6. 常见误区

❌ backlog 是最大连接数
✅ 它是 等待 accept 的已完成连接上限

❌ backlog 越大越好
✅ 太大可能占用内存、掩盖程序性能问题

❌ backlog 控制半连接
✅ 主要影响全连接队列


7. 调优建议(TCP 高并发场景)

# 提高全连接队列上限
net.core.somaxconn = 4096

# 提高半连接队列
net.ipv4.tcp_max_syn_backlog = 8192

# 防止 SYN 攻击
net.ipv4.tcp_syncookies = 1

应用层:

listen(fd, 4096);

8. 一句话总结

backlog 是 TCP 服务端在 accept 之前,内核为其预留的“已完成连接”的缓冲长度,是 TCP 三次握手后在 Linux 内核中的关键参数。

如果你愿意,我也可以画一张 TCP 队列 + backlog 的示意图,或者结合 Nginx / Redis / 自写 server 讲具体影响。

0 踩