linux - 我可以使用 SO_REUSEPORT 将单个 UDP 流分发到多个接收器线程吗?
问题描述
我的 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 流,上面的散列实现将产生所有被定向到同一接收器线程的数据包,从而阻碍我并行化工作的尝试。因此,问题是:有没有办法使用或其他机制从多个线程接收单个 UDP 数据包流?SO_REUSEPORT
请注意,我的应用程序可以处理数据包的重新排序;数据报格式化的协议包含排序信息,我可以使用这些信息在之后正确地重新排序它们。
解决方案
如果您在过去 3 年没有找到解决方案,请查看SO_ATTACH_REUSEPORT_CBPF
. 我们遇到了完全相同的问题,我们通过附加简单的 BPF 程序解决了这个问题,该程序随机分布数据报 mod n。
推荐阅读
- python - 为什么 to_sql 函数需要更多时间从 python 替换 MySQL 中的表?
- excel - Excel VBA - 带有 If 语句的用户窗体组合框
- c# - 如何使用 ElasticSearch Nest 版本 7.x 创建索引?
- python - 检测字符串是否是有效python代码的开头
- c# - 使用新命名空间重写方法 - Azure.Storage.Files.Shares
- selenium - 当我可以在源代码中看到时,为什么我无法使用 find_elements 抓取数据
- bash - 使用 Bash 脚本的 DB 命令输出列值过滤器
- python - Transformers 库中 Pegasus 模型的单词/句子的最大输入长度
- office-js - How to place outlook add-in in email itself for read email form
- java - How to connect web dashboard with android application and send data