【发布时间】:2018-08-01 01:32:08
【问题描述】:
我的 Linux 应用程序需要以每秒约 600,000 个数据包的速度接收单个 UDP 流,其中包含中等大小的数据包 (~1 KB)。我当前的实现很幼稚:它有一个简单的线程重复调用recv(),将接收到的数据放入队列中以由另一个线程处理。因此,接收线程只负责拉入数据包。
在我完成的一些初始测试中,在线程完全利用其 CPU 内核之前,我每秒只能接收 200,000-300,000 个数据包。这显然不足以满足每秒约 600,000 个数据包的目标。
理想情况下,我会找到某种方法来跨多个线程分配数据包接收负载。在寻找问题的解决方案时,我遇到了SO_REUSEPORT socket option,它允许将多个 TCP/UDP 线程绑定到同一个 IP/端口组合。起初,这似乎正是我想要的。
不过,文章也指出了这个细节:
传入的连接和数据报使用基于连接的 4 元组的哈希分配到服务器套接字,即对等 IP 地址和端口加上本地 IP 地址和端口。这意味着,例如,如果客户端使用同一个套接字将一系列数据报发送到服务器端口,那么这些数据报将全部定向到同一个接收服务器(只要它继续存在)。这简化了在客户端和服务器之间进行有状态对话的任务。
因此,如果我只有一个 UDP 流,上面的散列实现会产生所有数据包被定向到同一个接收器线程,从而阻碍我并行化工作的尝试。因此,问题是:有没有办法使用SO_REUSEPORT或其他机制从多个线程接收单个UDP数据包流?
请注意,我的应用程序可以处理数据包的重新排序;用于格式化数据报的协议包含排序信息,我可以使用这些信息在之后对它们进行正确重新排序。
【问题讨论】: