SO_REUSEPORT套接字服务器

时间:2018-09-11 06:00:22

标签: linux multithreading sockets

我一直在为Linux开发多线程套接字服务器,并且我正在尝试各种方法来多路复用I / O,以查看哪种方法最有效。

我已经有创建共享epoll / socket的代码-启用了EPOLLONESHOT-每个线程从中提取事件,然后在处理后在fd上重新布防EPOLLONESHOT。

((“ Processing”在这种情况下是指读到EAGAIN / EWOULDBLOCK,然后发送回一个简单的答复。基本上,我正在使用“ ab”进行测试,因此它发送HTTP GET请求,然后发送HTTP“ 200 OK”返回。)

但是我想尝试SO_REUSEPORT。因此,每个线程都有自己的epoll /套接字,绑定到同一端口。实际上,每个线程都是其自己的“微型服务器”,我们让内核在它们之间进行负载平衡。

我执行了accept(),为传入的连接获取fd,因此将其添加到epoll中。在该fd上完成处理后,我自然会调用close()结束对话。

但是,这似乎会间歇性地删除传入的接受(并且“间歇性地”是指它的行为就像竞争条件-有时以随机方式起作用,有时却不起作用)。

继续阅读,显然存在一个已知的错误,即accept()和close()之间可能存在竞争条件,因为close()会导致事物重新平衡,并且接受队列刚刚被重置,因此它们被丢弃了。

我正在尝试解决此问题的方法。

我曾经的一个想法是将接受者与epoll处理队列分开,以便关闭epoll上的fd不会清除该队列中的接受者。

但是这在逻辑上是行不通的,因为我不能同时在accept()和epoll_wait()上阻塞一个线程。为了正确地进行多路复用,我们必须阻止所有事件。

我的理解方式是,有多少个“微型服务器”和多个内核,每个服务器都固定在一个内核上。因此,它们确实都是并行运行的,没有上下文切换。

这意味着,尽管我可以产生一个新线程来处理新传入的fd-并使主线程处于循环中,仅将accept()保留-但这在某种程度上不利于固定CPU的目的,而多路复用的整个思想是摆脱“每个连接一个线程”的事情。

我已经查看了SO_REUSEPORT服务器的源代码,以了解其他人如何处理此问题,但是我所能找到的只是一个简单的演示,它不是多线程/多核的。

有人知道我如何解决这个问题,使多线程SO_REUSEPORT套接字服务器真正起作用吗?

1 个答案:

答案 0 :(得分:0)

在测试自己的服务器代码时,我的重点是服务器。很自然。

但是请注意,我在Internet上发现了一个示例,该示例设置了SO_RCVTIMEO套接字选项-接收超时-在将套接字fd从接受添加到epoll之前,我也尝试了此方法,现在所有程序都无需运行问题(一百万个请求与1000个并发,每个核心的使用率稳定在30-40%左右)。

我很想确切知道为什么它可以解决问题,但是我想这仅仅是因为我的服务器对通信客户端的延迟,问题等没有足够的容忍度,所以它一直卡在沟通中的任何麻烦-然后它将永远等待,因为没有超时。

将超时添加到所有操作是有道理的,以防万一,因为网络通信从来都不是100%完美的。而且,与编码一样,无论如何,人们都应该将所有输入视为不可靠和潜在的恶意。