-1

我正在以10Mbps的速率接收 UDP 数据包。每个数据包由大约1109 个字节组成。因此,我在eth0上收到的速度超过1pkt/ms。C 中的C 接收数据包并将数据包传递给 Java。Java 对数据包进行过滤和必要的处理。recvfrom()

瓶颈是:

  1. recvfrom()太慢了:获取时间超过 10 毫秒可能是因为它没有得到 CPU。

  2. 通过接口(JNI)将数据包从 C 传递到 Java 需要 1-2 毫秒。

  3. Java 本身处理数据包需要 0.5 到 1 秒,具体取决于是否需要进行数据库插入或图像处理。

所以,问题是许多延迟加起来,超过一半的数据包丢失。

可能的解决方案可能是:

  1. 完全不需要 C 语言recvfrom(),直接在 Java 中实现 UDP 获取(注意:首先,C 语言的 recvfrom() 被实现为接收原始数据包而不是 UDP)。此解决方案可以减少 JNI 传输延迟。

  2. 在Java中对UDP接收函数实现多线程。但是随后在 UDP 数据包中需要一个 ID 用于序列,因为在多线程中,传入数据包的顺序不能保证。(但是,在这个特定的程序中,需要订购数据包)。此解决方案可能有助于接收所有数据包,但需要修改发送数据的协议以添加序列标识符。由于多线程,接收方可能有更高的机会获得 CPU 并且可以快速获取数据包。

  3. 在 Java 中,阻塞队列可以实现为一个巨大的缓冲区,用于存储传入的数据包。Java 解析器然后可以使用来自该队列的数据包来处理它。但是,不确定接收器功能是否足够快并将所有接收到的数据包放入队列而不丢弃任何数据包。

我想知道哪些解决方案可能是最佳的,或者上述解决方案的组合将起作用。任何帮助或建议将不胜感激。

4

2 回答 2

2

这种爆发持续了多长时间?它是连续的并且会永远持续下去吗?然后你需要更强大的硬件来处理负载。可能是一些负载平衡,其中多个服务器处理传入数据。

爆发是否只持续很短的时间,比如最多一两秒?然后让下层尽可能快地读取所有数据包,并放入队列中,让上层在自己的时间内从队列中获取消息。

于 2016-03-02T13:07:23.390 回答
0

听起来您可能recvfrom()在阻塞模式下使用套接字调用,在这种情况下,直到下一个数据包到达它才会返回。如果数据包以 10 毫秒的间隔发送,可能是由于发送端的一些延迟,那么阻塞recvfrom()调用的循环似乎每个需要 10 毫秒。将套接字设置为非阻塞并使用类似的东西select()来决定何时调用它。然后分析所有内容以查看真正的瓶颈所在。我的赌注是一个或多个 JNI 直通。

请注意,这recvfrom()不是“C”函数,而是系统调用。Java 的函数只是在其上添加层。

于 2016-03-02T20:46:13.133 回答