我每秒收到~3000个UDP数据包,每个数据包的大小约为200字节。我写了一个java应用程序,它监听那些UDP数据包并将数据写入文件。然后,服务器以先前指定的速率发送15000条消息。写入文件后,它只包含~3500条消息。使用wireshark我确认我的网络接口收到了所有15000条消息。之后,我尝试更改套接字的缓冲区大小(最初为8496bytes):
(java.net.MulticastSocket)socket.setReceiveBufferSize(32*1024);
该更改将保存的消息数量增加到~8000。我不断将缓冲区大小增加到1MB。之后,保存的消息数量达到~14400。将缓冲区大小增加到更大的值不会增加保存的消息数。我想我已达到允许的最大缓冲区大小。不过,我需要捕获网络接口收到的所有15000条消息。
任何帮助将不胜感激。提前谢谢。
答案 0 :(得分:5)
闻起来像一个bug,很可能在你的代码中。如果UDP数据包通过网络传送,它们将排队等待本地传送,正如您在Wireshark中看到的那样。也许你的程序只是没有及时从其套接字读取进展 - 是否有专门的线程来完成这项任务?
您可以通过检测程序丢失哪些数据包取得一些进展。如果丢失的所有数据包都是早期数据包,则可能是在程序等待接收数据之前发送数据。如果他们都晚了,也许它会很快退出。如果它们是固定间隔,则代码中可能会出现一些问题,这些问题会导致接收数据包。等
无论如何,你似乎对丢失数据包非常焦虑。根据设计,UDP不是可靠的传输方式。如果丢失这些多播数据包对您的系统来说是一个问题(而不仅仅是出于性能原因而想解决的一个谜),那么系统设计是错误的。
答案 1 :(得分:1)
您似乎遇到的问题是您延迟写入文件。我会在写入文件之前将所有数据读入内存(或写入另一个线程中的文件)
然而,没有办法确保使用UDP接收100%的数据包而无法再次请求数据包(TCP为您做的事情)
答案 2 :(得分:1)
我看到您正在使用UDP发送文件内容。在UDP中,不保证数据包的顺序。如果您不担心订单,则将所有数据包放入队列并让另一个线程处理队列并将内容写入文件。这样,套接字读取器线程就不会因文件操作而被阻塞。
答案 3 :(得分:0)
接收缓冲区大小在OS级别配置。
例如在Linux系统上,如本文中的sysctl -w net.core.rmem_max=26214400
https://access.redhat.com/site/documentation/en-US/JBoss_Enterprise_Web_Platform/5/html/Administration_And_Configuration_Guide/jgroups-perf-udpbuffer.html
答案 4 :(得分:0)
这是仅Windows的答案,但是在我们的使用案例中,网络控制器卡属性的以下更改使 DRAMATIC 丢包率有所不同。
我们正在消耗大约200 Mbps的UDP数据,并且在中等服务器负载下正遭受大量数据包丢失。
使用的网卡是 Asus ROG Aerion 10G 卡,但是我希望大多数高端网络控制器卡都具有相似的性能。您可以通过设备管理器->网卡->右键单击->属性->高级选项访问它们。
1。增加接收缓冲区的数量:
默认值为512;我们可以将其增加到1024。在我们的情况下,可以接受更高的设置,但是当我们超过1024时,网卡将被禁用。网卡级别的可用缓冲区数量较大,使系统对传输延迟的容忍度更高。数据从网卡缓冲区到套接字缓冲区,我们的应用最终可以在其中读取数据。
2。将中断审核率设置为“关闭”:
如果我理解正确,则中断协调将多个“缓冲区填充”通知(通过中断)合并为一个通知。因此,CPU将较少中断,并在每次中断期间获取多个缓冲区。这样可以减少CPU使用率,但增加了准备好的缓冲区在取回之前被覆盖的可能性,以防中断服务延迟。
此外,正如 Len Holgate 在评论中建议的那样,我们增加了套接字缓冲区的大小(如OP所做的那样),并在套接字级别启用了循环缓冲区 ,这也应增加对套接字缓冲区处理延迟的容忍度。