epoll_create和fork顺序的影响
先fork再epoll_create
先fork再epoll的话底层是多棵红黑树,这时候如果不用SO_REUSEPORT选项的话,会有惊群现象,例如accept请求来时,多个进程都对这个socket注册了感兴趣的event,所以所有进程都会被唤醒(如果消息处理速度很快的话,有可能不会有惊群现象,因为再准备通知其他进程的时候消息已经处理完毕),这个时候要解决epoll下的accept惊群的思路有两个
- 使用SO_REUSEPORT
- 使用EPOLLEXCLUSIVE选项。该选项是在linux 4.5+的版本中引入的,需要在epoll_ctl加入server的fd时指定epoll_event中的events选项与EPOLLEXCLUSIVE进行或操作即可。
libev的文档中提到部分跟这个相关的内容:
The epoll mechanism deserves honorable mention as the most misdesigned of the more advanced event mechanisms: mere annoyances include silently dropping file descriptors, requiring a system call per change per file descriptor (and unnecessary guessing of parameters), problems with dup, returning before the timeout value, resulting in additional iterations (and only giving 5ms accuracy while select on the same platform gives 0.1ms) and so on. The biggest issue is fork races, however - if a program forks then Iparent and child process have to recreate the epoll set, which can take considerable time (one syscall per file descriptor)
and is of course hard to detect.
因此,尽量在fork后再进行epoll_create,如果epoll_create一定要先进行,那建议在子进程中关闭最初的epoll。