捋一捋 backlog 的作用

流过昼夜 提交于 2021-02-11 07:44:12

我们知道在 socket 编程中,服务端需要经历 listen → bind → accept 这么几个过程;而客户端需要经历 connect → receive 的过程。其中服务端在 bind 的时候需要指定 backlog 的大小。网上的好多文章,感觉都没有讲清楚这个参数的作用,特在此好好捋一下。方便他人,同时也方便自己。


术语约定:


  • 未完成:半开,处于 SYN_RCVD 状态

  • 已完成:已连接但未 ACCEPT,处于 ESTABLISHED 状态

  • 已完毕:已连接且已 ACCEPT,处于 ESTABLISHED 状态


以下我们这里只讨论未完成和已完成,因为已完毕的都是由应用自己维护。直接上结论:


linux 2.2 之前:

    backlog = 未完成 + 已完成


linux 2.2 之后:

    backlog = 已完成


需要注意的是,linux 2.2 之后,半连接 syn 队列的长度由 max(64, /proc/sys/net/ipv4/tcp_max_syn_backlog) 所决定;而已完成的队列长度其实是由 min(backlog, somaxconn) 所决定。somaxconn 这个值,在 kernel 2.4.25 之前,都是写死在代码里的,默认为 128。在 kernel 2.4.25 之后,在 /proc/sys/net/core/somaxconn 。


那么问题来了,怎样才能查看进程的 backlog 数量呢?


ss -anp | grep nginx


就可以了。需要注意的是,使用该命令获取到的 Recv-Q/Send-Q 在 LISTEN 状态以及非 LISTEN 状态所表达的含义是不同的:




  • LISTEN 状态: Recv-Q 表示的是当前已完成队列的大小;Send-Q 表示的则是最大的 listen backlog 数值。

  • 其余状态: Recv-Q 表示 receive queue 中的 bytes 数量;Send-Q 表示 send queue 中的 bytes 数值。


所以上图中显示的是,nginx 的 backlog 为 511,当前已完成队列的大小为 0。那么还有个问题,就是未完成队列在哪里看?很简单:


ss -anp | grep nginx | grep -c SYN_RECV

本文分享自微信公众号 - poslua(poslua)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!