简而言之,SO_REUSEPORT
套接字选项允许在ip:port对上创建多个套接字。例如,program1
和program2
都可以为同一端口和IP调用函数链socket()->bind()->listen()->accept()
,内核调度程序将在这两个程序之间均匀分配传入连接。
我认为使用此选项,您可以摆脱使用fork()
来生成其他工作人员,并且只需运行新的程序实例。
我根据这个逻辑写了一个简单的epoll套接字服务器,并用weighttp测试它:
weighttp -n 1000000 -c 1000 -t 4 http://127.0.0.1:8080/
对于两个正在运行的实例,对于一个运行实例,结果为~44000 RPS - 接近~51000 RPS。我对7000 RPS差异感到非常惊讶。
在此测试之后,我在fork()
之前添加listen()
并运行一个服务器实例,所以现在它具有与先前实现相同的逻辑 - 两个使用epoll循环侦听套接字的进程,但是{{1} }只在socket()->bind()
之前调用一次,第二个进程在fork()
调用之前接收FD副本。
我再次运行测试,显示~50000 RPS!
所以,我的问题非常简单:在这种情况下,listen()
有什么神奇之处,以及为什么它比两个独立的进程更快,它拥有fork()
?内核为调度做同样的工作,我没有看到任何重要的区别。
答案 0 :(得分:0)
将此评论标记为已回答的问题:由于我的研究,内部OS调度程序远非最佳并依赖于硬件。更好的是使用用户土地调度程序。