“丢失”的UDP数据包(JBoss + DatagramSocket)

时间:2011-02-23 18:34:36

标签: java udp datagram

我开发了一些基于JBoss + EJB的企业应用程序。我的模块需要处理大量传入的UDP数据包。我已经完成了一些负载测试,看起来如果以11ms的间隔发送数据包,一切都很好,但是在10ms间隔的情况下,一些数据包会丢失。在我看来这是相当奇怪的,但我做了10 / 11ms间隔负载测试比较几次,它总是相同的结果(10毫秒 - 一些“丢失”数据包,11毫秒 - 一切都很好。)

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

我发现接收缓冲区大小(SO_RCVBUF)具有默认的57344值(可能是它的底层IO网络缓冲区依赖)。我怀疑,也许当这个缓冲区满了,然后新的传入UDP数据报被拒绝。我尝试将此值设置为更高,但我注意到,如果我夸大,缓冲区将返回其默认大小。如果它的底层依赖,我如何从JBoss级别找出某个OS /网卡的最大缓冲区大小?

是否可能是由接收缓冲区大小引起的,或者57344值是否足以处理大多数情况?你对这些问题有经验吗?

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

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

慢速处理不太可能导致此问题。目前,singleton组件在循环中保持对DatagramSocket调用receive方法的引用。收到数据包时,会将其传递给队列,并通过从池无状态组件中选择进行处理。 “Facade”Singleton仅负责接收数据包并将其传递给处理(它不等待处理完成事件)。

提前致谢, 彼得

4 个答案:

答案 0 :(得分:5)

UDP不保证传递,因此您可以调整参数,但不能保证邮件将被传递,特别是在数据传输非常大的情况下。

如果您需要保证交付,则应使用TCP。

如果您需要(或想要)使用UDP,您可以使用数字对每个数据包进行编码,并发送预期的数据包数。例如,如果您发送了10个大数据包,则可以包含以下信息:数据包1/10,数据包2/10等。这样您至少可以判断您是否未收到所有数据包。如果您还没有收到它们,您可以发送请求重新发送丢失的数据包。

答案 1 :(得分:3)

UDP本质上是不可靠的。

数据报可以在发送方和接收方之间的任何位置丢弃,即使在接收方的低于代码的级别也是如此。将recv缓冲区设置为更大的大小可能有助于机器中的网络代码缓冲更多的数据报,但您应该期望一些数据报无论如何都会丢失。

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

[重新编辑...]什么处理你的队列以及生产者和消费者之间的锁定如何工作?更改你的代码,以便recv逻辑简单地增加一个计数并丢弃数据并循环回来,看看你是否丢失了更少的数据报;无论哪种方式,UDP是不可靠的,你将丢弃丢弃的数据报,你应该期待并处理它。担心它意味着你专注于错误的问题;利用你得到的数据并假设你不会得到太多的数据然后你的程序即使网络拥挤而你的数据报的大部分被丢弃也会有效。

总之,这就是UDP的方式。

答案 2 :(得分:2)

在您的测试中,缓冲区中最多只能有两个数据包,因此如果每个数据包小于28KB,这应该没问题。

如您所知UDP是有损的,但您应该能够每10 ms发送一个以上的数据包。我建议你写一个简单的接收器,它只是监听数据包,以确定它是你的应用程序或网络/操作系统级别的东西。 (我怀疑后者)

答案 3 :(得分:1)

我不知道Java但是...... API是否允许您为数据报调用异步侦听/接收:

  • 使用O / S API进行接收(将应用程序级缓冲区作为参数传递)
  • (等等什么都没收到......)
  • (O / S从网络收到一些东西......)
  • O / S将收到的数据包放入缓冲区并完成/返回您的API调用

如果这是真的,那么我建议你做几个API调用的并发实例,这样就有几个可以接收多个数据包的并发应用程序级缓冲区。