我有一个java服务器应用程序。
while(true)
{
serverSocket.receive(receivePacket);
process(receivePacket);
serverSocket.send(sendPacket);
try {
Thread.sleep(10000); // sleep for 10s
} catch (InterruptedException e) {
e.printStackTrace();
}
}
它接收并处理 1 个 UDP 数据包/10 秒。
如果我向服务器发送 10 个 UDP 数据包,则处理 1 个数据包,然后进入睡眠状态 10 秒。所以我在100秒后收到第10个数据包的响应。
如果我这样做,则服务器1将运行 CentOS 6.4 版(最终版)。
Server 1: cat /proc/net/udp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops
110: 00000000:10AE 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 85635445 2 ffff880836e6d100 0
111: 00000000:10AF 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 85635446 2 ffff88083913a1c0 0
115: 00000000:15B3 00000000:0000 07 00000000:00004FC8 00:00000000 00000000 0 0 390649369 2 ffff880434ae7440 0
117: 02FE6341:0035 00000000:0000 07 00000000:00000000 00:00000000 00000000 0 0 353480394 2 ffff8808367f9040 0
如果我在服务器 2 中做同样的事情:
Server 2: cat /proc/net/udp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops
4: FCA9C11F:C36F 8C719AC6:0035 01 00000000:00000000 00:00000000 00000000 0 0 2983494501 2 ffff880169aff4c0 0
5: FCA9C11F:D3F0 8C719AC6:0035 01 00000000:00000000 00:00000000 00000000 0 0 2983494485 2 ffff8801b9bbedc0 0
16: 7A52BB59:007B 00000000:0000 07 00000000:00000000 00:00000000 00000000 38 0 2438608536 2 ffff8807656764c0 0
16: A2EE0D55:007B 00000000:0000 07 00000000:00000000 00:00000000 00000000 38 0 2438608045 2 ffff88077ccdd7c0 0
16: A58F466D:007B 00000000:0000 07 00000000:00000000 00:00000000 00000000 38 0 2438607809 2 ffff8801129f6240 0
它们都是 centos 服务器,我们可以看到,由于应用程序处理数据包的速度比传入服务器的数据慢,所以 server1 的 rx_queue 缓冲区正在增加。
我在 server2 中做了完全相同的事情,但在 server2 中 rx_queue 没有增加。我做错了什么/理解错了吗?
答案1
我在 Ubuntu 18.04 LTS(内核 4.15.0-38)上看到类似的问题。但在我的 Debian 9.5(内核 4.9.110-3)机器上却没有发生这种情况。似乎是较新内核中的错误?
重现该问题的一个简单方法是使用 netcat。客户端和服务器可以位于本地或位于不同的机器上。
- 在一个终端中运行 netcat 服务器: nc -u -l 1234
- 在另一个终端中运行netcat客户端:nc -u 127.0.0.1 1234
- 在客户端中输入短信“a”并按回车键。
- 在第三个终端中检查recv-q长度:netstat -plan |正则表达式 1234
在 Ubuntu 上,即使 netcat 已从套接字读取消息并打印它,接收 udp 套接字也将具有非空的 recv-q(2 字节消息为 768 字节)。我发现 recv-q 一直增长到大约 52k,然后它重置回零。
在 Debian 上,只要 udp 套接字耗尽的速度快于接收数据包的速度,recv-q 就始终为零。
还发现了这个内核错误报告:/proc/net/udp 中的 UDP rx_queue 计算不正确
答案2
请原谅我对 StackExchange 的这一部分不熟悉,所以我发布的是答案而不是评论。
Ubuntu 18.04 LTS
我在(kernel )上遇到了与@Neopallium相同的问题4.15.0-36
。从我的测试来看,人为设置net.core.rmem_max=26214400
和net.core.rmem_default=26214400
(分别25MB
)并运行我的 UDP 服务器应用程序,在整个测试过程中没有 UDP 数据报积压,我看到计数器rx_queue
上升到大约00000000:006xxxxx
或~6MB+
,然后计数器突然重置为0
。这大约是计数器重置之前1/4
的时间。net.core.rmem_max
在和的Ubuntu 18.04 LTS
默认值上,因此@Neopallium 看到他的计数器在重置之前上升到大约(大约)也就不足为奇了。net.core.rmem_default
net.core.rmem_max
212992
52k
1/4
212k
/proc/net/udp
以下是接近重置点时应用程序的输出:
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops
1256: 00000000:7530 00000000:0000 07 00000000:00632240 00:00000000 00000000 0 0 94457826 2 0000000000000000 0
这是过去 45 分钟内我的 grafana 套接字图的屏幕截图: