如何监控Linux UDP缓冲区的可用空间?
- 2024-11-07 08:55:00
- admin 原创
- 24
问题描述:
我在 Linux 上有一个 java 应用程序,它打开 UDP 套接字并等待消息。
在高负载下运行几个小时后,出现数据包丢失,即数据包由内核接收,但我的应用程序未接收(我们在嗅探器中看到丢失的数据包,在 netstat 中看到 UDP 数据包丢失,但在应用程序日志中看不到这些数据包)。
我们尝试扩大套接字缓冲区,但这没有帮助——我们开始比以前更晚丢失数据包,但就是这样。
为了进行调试,我想知道在任何给定时刻 OS UDP 缓冲区有多满。谷歌搜索,但没有找到任何东西。你能帮助我吗?
PS 各位,我知道 UDP 不可靠。但是 - 我的电脑接收所有 UDP 消息,而我的应用程序无法使用其中的一些消息。我想最大限度地优化我的应用程序,这就是我提出这个问题的原因。谢谢。
解决方案 1:
UDP 是一种完全可行的协议。这和老套的“用合适的工具做合适的工作”是一样的道理!
如果您有一个程序等待 UDP 数据报,然后处理这些数据报,然后再返回等待下一个数据报,那么您经过的处理时间需要始终快于数据报的最坏情况到达率。如果不是,那么 UDP 套接字接收队列将开始填满。
对于短时间的突发情况,这是可以容忍的。队列完全按照其预期的方式工作 - 将数据报排队,直到您准备好为止。但是,如果平均到达率经常导致队列积压,那么是时候重新设计您的程序了。这里有两个主要选择:通过巧妙的编程技术减少已用处理时间,和/或多线程处理程序。也可以在程序的多个实例之间进行负载平衡。
如上所述,在 Linux 上,您可以检查 proc 文件系统以获取有关 UDP 正在执行的操作的状态。例如,如果我是cat
节点/proc/net/udp
,我会得到如下信息:
$ 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
我对我的小程序的解决方案是多线程。
干杯!
解决方案 2:
Linux 提供了文件/proc/net/udp
和/proc/net/udp6
,其中列出了所有打开的 UDP 套接字(分别用于 IPv4 和 IPv6)。在这两个文件中,tx_queue
和列rx_queue
以字节为单位显示传出和传入队列。
如果一切按预期运行,您通常不会在这两列中看到任何非零值:只要您的应用程序生成数据包,它们就会通过网络发送,并且只要这些数据包从网络到达,您的应用程序就会被唤醒并接收它们(调用立即返回)。如果您的应用程序打开了套接字但未调用以接收数据,或者它处理此类数据的速度不够快,recv
您可能会看到上升。rx_queue
`recv`
解决方案 3:
rx_queue 会告诉您任何给定时刻的队列长度,但不会告诉您队列有多满,即高水位标记。没有办法持续监控此值,也没有办法以编程方式获取它(请参阅如何获取 UDP 套接字的排队数据量?)。
我能想到的唯一监控队列长度的方法是将队列移到您自己的程序中。换句话说,启动两个线程——一个线程以最快的速度读取套接字并将数据报转储到您的队列中;另一个线程让您的程序从该队列中拉取数据包并处理数据包。当然,这假设您可以确保每个线程都在单独的 CPU 上。现在您可以监控您自己的队列的长度并跟踪高水位标记。
解决方案 4:
过程很简单:
如果需要,请暂停申请流程。
打开 UDP 套接字。如有必要,您可以使用 从正在运行的进程中获取它
/proc/<PID>/fd
。或者您可以将此代码添加到应用程序本身并向其发送信号 - 当然,它已经打开了套接字。recvmsg
尽快建立紧密循环。计算一下您获得了多少个数据包/字节。
这将丢弃当前缓冲的所有数据报,但如果这破坏了您的应用程序,那么您的应用程序就已经损坏了。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件