我开发一些基于JBoss + EJB的企业应用程序的一部分。我的模块需要处理大量传入的UDP数据包。我已经进行了一些负载测试,它看起来在发送间隔为11ms的数据包的情况下一切都很好,但是在间隔为10ms的情况下,某些数据包会丢失。在我看来,这很奇怪,但是我多次进行了10/11ms间隔负载测试比较,并且结果始终相同(10 ms-一些“丢失”的数据包,11ms-一切都很好)。

如果同步出现问题,我希望它在11ms测试(至少丢失一个数据包,或至少一个错误的计数器值)的情况下也可见。
因此,如果不是因为同步,那么接收数据包的DatagramSocket可能无法正常工作。

我发现接收缓冲区大小(SO_RCVBUF)具有默认的57344值(可能与基础IO网络缓冲区有关)。我怀疑,也许当此缓冲区已满时,新的传入UDP数据报就会被拒绝。我尝试将此值设置为更高,但是我发现如果夸大了,缓冲区将返回其默认大小。如果它取决于底层,如何从JBoss级别找出某些OS/网卡的最大缓冲区大小?

这可能是由于接收缓冲区大小引起的,还是57344的值足以应付大多数情况?您是否有处理此类问题的经验?

我的DatagramSocket上没有设置超时。我的UDP数据报包含大约70个字节的数据(不包括数据报头的值)。

[已编辑]
我必须使用UDP,因为我收到Cisco Netflow数据-网络设备使用该协议(protocol)发送一些流量统计信息。另外,我对发送的字节格式没有任何影响(例如,我无法为数据包添加计数器等)。预计不会处理所有数据包(某些数据报可能会丢失),但是我希望我将处理大多数数据包。在10ms的间隔测试中,大约有30%的数据包丢失。

缓慢的处理不太可能导致此问题。当前,单例组件保留对DatagramSocket的引用,该引用在一个循环中调用接收方法。接收到数据包后,会将其传递到队列,并从池无状态组件中进行选择。 “Facade” Singleton仅负责接收数据包并将其传递到处理过程(它不等待处理完成事件)。

提前致谢,
皮特

最佳答案

UDP本质上是不可靠的。

数据报可以在发送方和接收方之间的任何位置扔掉,甚至可以在低于代码级别的接收方内丢弃。将recv缓冲区设置为更大的大小可能会帮助您机器中的网络代码缓冲更多的数据报,但是您应该期望某些数据报仍然会丢失。

如果您的recv逻辑花费的时间太长(即比新数据报到达所花费的时间更长),那么您将永远落后,最终总是会错过数据报。您所能做的就是确保您的recv代码运行得尽可能快,也许将入站数据报移到队列中并“稍后”或在另一个线程上进行处理,但这只会将您的问题转移到您拥有一个问题的地方。不断增长的队列。

[重新编辑...]并且什么在处理您的队列,以及生产者和消费者之间的锁定如何工作?更改您的代码,以便recv逻辑仅增加一个计数并丢弃数据并循环回去,看看是否丢失了更少的数据报;无论哪种方式,UDP都是不可靠的,您将拥有被丢弃的数据报,并且您应该只是期望并处理它。担心它意味着您正在专注于错误的问题。利用您获取的数据并假设您不会得到很多数据,那么即使网络出现拥塞并且大部分数据报被丢弃,您的程序仍然可以运行。

总之,UDP就是这样。

10-07 19:02
查看更多