backlog 是 Linux 网络编程中的一个重要概念,主要出现在 TCP 连接建立过程中。以下是 backlog 产生的常见场景:
当服务器调用 listen()
函数时,会指定一个 backlog 参数,这个参数决定了已完成连接队列(SYN队列)的最大长度。
典型场景:
- 客户端发送 SYN 包
- 服务器收到后放入 SYN 队列(半连接队列)
- 服务器响应 SYN-ACK
- 客户端回应 ACK 后,连接从 SYN 队列移到 accept 队列(全连接队列)
- 应用调用 accept()
从队列中取出连接
当服务器面临大量并发连接请求时:
- 如果新连接到达速度超过 accept()
处理速度
- 或者应用暂时无法调用 accept()
- 已完成三次握手的连接会在 accept 队列中堆积
- 当超过 backlog 指定的大小时,新连接会被丢弃或拒绝
恶意攻击者发送大量 SYN 包但不完成握手: - 每个 SYN 包都会在服务器创建半连接条目 - 这些条目会占用 SYN 队列(半连接队列)空间 - 当队列满时,合法用户无法建立新连接
当服务器负载过高时:
- CPU 资源不足导致 accept()
处理变慢
- accept 队列快速填满
- 新连接无法进入队列而被丢弃
常见配置问题: - backlog 值设置过小(默认值通常为 128) - 系统 somaxconn 参数限制 - 文件描述符限制过小
影响 backlog 行为的几个重要内核参数:
- net.core.somaxconn
- 系统级别的最大 backlog 值
- net.ipv4.tcp_max_syn_backlog
- SYN 队列的最大长度
- net.ipv4.tcp_syncookies
- SYN Flood 防护机制
当怀疑 backlog 相关问题时,可以使用:
- ss -lnt
查看监听套接字的 Send-Q(实际 backlog 值)
- netstat -s | grep listen
查看因 backlog 满被丢弃的连接数
- dmesg
查看内核日志中可能的警告信息
理解这些场景有助于合理配置 backlog 参数,优化服务器在高并发环境下的性能表现。