繁体   English   中英

如何监视Linux UDP缓冲区的可用空间?

[英]How to monitor Linux UDP buffer available space?

我在linux上有一个Java应用程序,它可以打开UDP套接字并等待消息。

在高负载下运行了几个小时之后,有一个数据包丢失,即数据包被内核接收,但不是由我的应用程序接收(我们在嗅探器中看到丢失的数据包,在netstat中看到UDP数据包丢失,我们没有看到这些数据包)在我们的应用日志中)。

我们尝试扩大套接字缓冲区,但这并没有帮助-我们早些时候就开始丢失数据包,仅此而已。

对于调试,我想知道在任何给定时刻OS udp缓冲区有多满。 谷歌搜索,但没有找到任何东西。 你能帮助我吗?

PS伙计们,我知道UDP不可靠。 但是-我的计算机收到所有UDP消息,而我的应用无法使用其中的一些消息。 我想最大程度地优化我的应用,这就是问题的原因。 谢谢。

UDP是一种完全可行的协议。 这是正确工具的正确案例,适用于正确的工作!

如果您有一个程序等待UDP数据报,然后先处理它们,然后再返回以等待另一个数据报,则您经过的处理时间必须始终比最坏情况下的数据报到达率要快。 如果不是,则UDP套接字接收队列将开始填充。

短时间突发可以忍受。 队列完全按照预期的方式工作-将数据报排队,直到您准备就绪为止。 但是,如果平均到达率经常导致队列积压,那么该重新设计程序了。 这里有两个主要选择:通过巧妙的编程技术减少经过的处理时间,和/或对程序进行多线程处理。 也可以在程序的多个实例之间进行负载平衡。

如前所述,在Linux上,您可以检查proc文件系统以获取有关UDP最新状态的状态。 例如,如果我将/proc/net/udp节点/proc/net/udp cat ,则会得到如下所示的内容:

$ cat /proc/net/udp   
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode ref pointer drops             
  40: 00000000:0202 00000000:0000 07 00000000:00000000 00:00000000 00000000     0        0 3466 2 ffff88013abc8340 0           
  67: 00000000:231D 00000000:0000 07 00000000:0001E4C8 00:00000000 00000000  1006        0 16940862 2 ffff88013abc9040 2237    
 122: 00000000:30D4 00000000:0000 07 00000000:00000000 00:00000000 00000000  1006        0 912865 2 ffff88013abc8d00 0         

由此,我可以看到用户ID为1006的套接字正在端口0x231D(8989)上侦听,并且接收队列大约为128KB。 由于128KB是我系统上的最大大小,这告诉我我的程序在跟上到达的数据报方面非常脆弱。 到目前为止,已经有2237个丢弃,这意味着UDP层无法将更多数据报放入套接字队列,而必须丢弃它们。

您可以观察程序随时间的行为,例如使用:

watch -d 'cat /proc/net/udp|grep 00000000:231D'

还要注意,netstat命令执行的操作大致相同: netstat -c --udp -an

我的weenie程序的解决方案是多线程。

干杯!

Linux提供了/proc/net/udp/proc/net/udp6 ,其中列出了所有打开的UDP套接字(分别用于IPv4和IPv6)。 在这两个字段中,列tx_queuerx_queue字节为单位显示了传出队列和传入队列。

如果一切正常,在这两列中通常不会看到任何与零不同的值:应用程序生成数据包后,它们将通过网络发送,而一旦这些数据包从网络到达,则应用程序将被唤醒并接收它们( recv调用立即返回)。 如果您的应用程序打开了套接字但没有调用recv来接收数据,或者它没有足够快地处理此类数据,则可能会看到rx_queue上升。

rx_queue会告诉您任何给定时刻的队列长度,但不会告诉您队列已满,即高水位线。 无法持续监控此值,也无法以编程方式获取它(请参阅如何获取UDP套接字的排队数据量? )。

我可以想象监控队列长度的唯一方法是将队列移到您自己的程序中。 换句话说,启动两个线程-一个正在尽可能快地读取套接字并将数据报转储到您的队列中; 另一个是您的程序从此队列中提取并处理数据包。 当然,这假定您可以确保每个线程都在单独的CPU上。 现在,您可以监视自己的队列的长度并跟踪高水位线。

过程很简单:

  1. 如果需要,请暂停申请过程。

  2. 打开UDP套接字。 如有必要,可以使用/proc/<PID>/fd从正在运行的进程中捕获它。 或者,您可以将此代码添加到应用程序本身并发送信号-当然,它已经打开了套接字。

  3. 尽快以紧密循环调用recvmsg

  4. 计算您获得了多少个数据包/字节。

这将丢弃当前缓冲的所有数据报,但是如果这破坏了您的应用程序,则您的应用程序已被破坏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM