简而言之,SO_REUSEPORT
套接字选项允许在 ip:port 对上创建多个套接字。例如,program1
和program2
都可以调用函数链socket()->bind()->listen()->accept()
对于相同的端口和IP,内核调度程序将在这两个程序之间均匀分配传入连接。
我假设使用此选项,您可以摆脱使用 fork()
来生成额外的工作进程,并且可以简单地运行新的程序实例。
我根据这个逻辑写了一个简单的epoll套接字服务器,并用weighttp测试它:
weighttp -n 1000000 -c 1000 -t 4 http://127.0.0.1:8080/
对于两个正在运行的实例,结果约为 44000 RPS,对于一个正在运行的实例,结果约为 51000 RPS。我对 7000 RPS 的差异感到非常惊讶。
在此测试之后,我在 listen()
之前添加 fork()
并运行一个服务器实例,因此现在它具有与之前的实现相同的逻辑 - 两个进程epoll 循环监听套接字,但 socket()->bind()
仅在 fork()
之前调用一次,第二个进程接收它的 FD 副本用于 listen( )
调用。
我再次运行测试,结果显示 ~50000 RPS!
所以,我的问题非常简单:在这种情况下,fork()
有什么魔力,为什么它比两个拥有自己 socket()
的独立进程运行得更快?内核在调度方面做同样的工作,我没有看到任何重要的区别。
最佳答案
发表此评论以标记已回答的问题:根据我的研究,内部操作系统调度程序远非最佳,并且取决于硬件。更好的是使用用户态调度程序。
关于c - SO_REUSEPORT 与 epoll 和多进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28993184/