SO_REUSEPORT 使用 epoll 和多进程

SO_REUSEPORT with epoll and multiple process

简而言之,SO_REUSEPORT 套接字选项允许在 ip:port 对上创建多个套接字。例如,program1program2 都可以为相同的端口和 IP 调用函数链 socket()->bind()->listen()->accept(),内核调度程序将在这两个程序之间平均分配传入连接。

我假设使用此选项,您可以摆脱使用 fork() 来产生额外的工人,并且可以简单地 运行 新程序实例。

我写了一个简单的epoll socket server,基于这个逻辑,用weighttp测试了一下:

weighttp -n 1000000 -c 1000 -t 4 http://127.0.0.1:8080/

对于两个 运行ning 实例,结果是 ~44000 RPS,对于一个 运行ning 实例 - 接近 ~51000 RPS。我对 7000 RPS 的差异感到非常惊讶。

在这个测试之后我在 listen() 和 运行 之前添加了 fork() 一个服务器实例,所以现在它与之前的实现具有相同的逻辑 - 两个带有 epoll 循环监听套接字的进程,但是 socket()->bind()fork() 之前只调用了一次,第二个进程收到它的 FD 副本以供 listen() 调用。

我运行再次测试,结果显示~50000 RPS!

所以,我的问题很简单:在这种情况下 fork() 有什么魔力,为什么它比两个独立的进程有自己的 socket() 更快?内核做同样的调度工作,我看不出有什么重要的区别。

发表此评论以将问题标记为已回答:根据我的研究,内部 OS 调度程序远非最佳并且取决于硬件。更好的是使用用户空间调度程序。