在真正 accept 之前暂存待握手连接的内核队列

TCP backlog 收纳还在握手中的连接

一个监听中的 TCP 套接字有两个队列,不是一个;而本文标题里那个 sysctl 管的,恰恰是几乎从不丢东西的那一个。传给 listen(2) 的 backlog 是 accept 队列,装的是已经完成握手、正等应用来取走的连接;SYN 队列装的才是半开请求。把两者混为一谈,就会开错药方。 这件事值得掰开,因为那句著名的建议——把 tcp_max_syn_backlog 调大——基本已经过时。tcp_syncookies 默认就是 1,而按 listen(2) 的说法,一旦启用 syncookies,SYN 队列就没有逻辑上的长度上限,这个设置会被忽略。真正会卡住你的是 accept 队列,以及应用调用 accept() 的速度。 backlog 参数管的是 accept 队列 listen(2) 明确写着,这个行为在 Linux 2.2 就变了:backlog 现在指的是「已完成建立、正等待被 accept 的套接字队列长度」,而不是半开请求的数量。半开队列由 /proc/sys/net/ipv4/tcp_max_syn_backlog 单独限制。而如果 backlog 参数超过 /proc/sys/net/core/somaxconn,它会被静默截断到那个值——Linux 5.4 之后是 4096,之前是 128。所以在默认配置的机器上写 listen(8192),实际拿到的是 4096,而且不会有任何日志告诉你。 ...

三月 24, 2028 · 2 分钟 · XB Field Notes