为什么 CentOS 服务器中 /proc/net/udp 显示错误的 rx_queue 大小?

为什么 CentOS 服务器中 /proc/net/udp 显示错误的 rx_queue 大小?

我有一个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。客户端和服务器可以位于本地或位于不同的机器上。

  1. 在一个终端中运行 netcat 服务器: nc -u -l 1234
  2. 在另一个终端中运行netcat客户端:nc -u 127.0.0.1 1234
  3. 在客户端中输入短信“a”并按回车键。
  4. 在第三个终端中检查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=26214400net.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_defaultnet.core.rmem_max21299252k1/4212k

/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 套接字图的屏幕截图:

在此输入图像描述 就像@Neopallium 我倾向于相信这是一个内核错误。

相关内容