「我正在参与掘金会员专属活动-源码共读第一期,点击参与」
一、Netty中backlog参数的含义
Netty的channel配置中有一个NioChannelOption.SO_BACKLOG选项,这个参数值会在底层传递给Net.listen函数。
想搞清楚这参数的含义,可以参考一下linux手册中的解释
"The backlog argument defines the maximum length to which the queue of pending connections for sockfd may grow."
backlog参数代表了tcp全连接队列的长度。当tcp连接三次握手成功后,状态为ESTAB且该连接并没有被应用程序的accept()函数取走时,该连接就被放置在全连接队列中。
全连接队列容量不足时,新的ESTAB状态连接无处安放,就会造成连接失败。所以说该参数对程序并发性的影响还是很大的。
该参数不仅在应用程序中可以配置, 在内核参数中也有对应的配置。
在linux中相关的内核参数是net.core.somaxconn
二、实践中的注意事项
Netty程序backlog参数与内核参数不一致时会发生什么?
值得注意的是backlog的值在内核参数与程序参数不一致时会取两者的较小值。min(backlog, somaxconn)
Netty中backlog的默认值是什么?
通过追踪Netty源码,可以看到在linux环境下Netty的backlog默认值和"/proc/sys/net/core/somaxconn"中的配置是一致的。
如何验证backlog配置是否生效?
程序启动后监听了某个端口, 如何能看到该监听的全连接队列长度呢?
在linux环境中可以使用ss命令。
ss命令的第三列参数Send-Q就代表了accept queue的长度。
三、实测
针对backlog参数的配置做以下测试,验证对该参数的理解是否正确。
| case | 内核参数 | Netty backlog参数 | 预期aceetp queue大小 |
|---|---|---|---|
| case1: Netty不设置backlog参数 | 666 | 不设置 | 666 |
| case2: Netty backlog参数大于内核参数 | 128 | 511 | 128 |
| case3: Netty backlog参数小于内核参数 | 1024 | 511 | 511 |
case1
修改内核参数somaxconn为666
不设置Netty backlog参数
启动程序后ss -antl结果 (Netty程序监听端口为7777)
case2
修改内核参数somaxconn为128
设置Netty backlog参数为511
启动程序后ss -antl结果 (Netty程序监听端口为7777)
case3
修改内核参数somaxconn为1024
设置Netty backlog参数为511
启动程序后ss -antl结果 (Netty程序监听端口为7777)
测试结论
这三个case的测试结果都符合预期, 验证了以下结论(在linux环境下)
-
accept queue长度取程序backlog参数和内核参数somaxconn的较小值。
-
Netty中backlog的默认值和内核参数一致。
四、总结
backlog是个很重要的参数。
设置过小: accept queue达到容量上限后, 后续的连接无法成功建立, 会成为程序的并发瓶颈。
设置过大: 在处理性能不足时大量的连接积压会造成客户端超时,且连接积压时消耗更多的系统资源(例如内存)。
那如何设置backlog参数还是要根据程序的性能测试、QPS等综合考量, 实际应用中对该accept queue的状态保持关注适时调整。
使用时要注意仅仅在程序中配置backlog是不行的, 要关注内核参数(linux环境中是net.core.somaxconn),当两者不一致时最终实际生效的是两者较小的值。