Nginx惊群

Nginx采用的是多进程模型,master进程创建好须要listen的socket fd以后,而后fork出N个worker进程。若是全部worker进程同时监听这个fd的事件,当有新一个链接到来时,这些进程会被同时唤醒去处理事件——accept。可是只有一个进程的accept会成功,而其余进程都会失败,这样的现象叫作惊群,会极大影响Nginx的性能。linux

其实,linux2.6内核已经解决了accept系统调用自己的惊群问题了。若是在父进程中listen,而后fork出的全部子进程都accept这个fd。当新链接过来时,仅有一个子进程的accept会返回,其余子进程则继续阻塞在accept调用上。可是对于Nginx的epoll循环来讲,这个问题依然存在,由于监听的socket依然会同时产生可读事件,把阻塞在epoll_wait上的全部worker所有唤醒。负载均衡

Nginx中处理epoll时惊群问题的思路很简单,引入了一个互斥锁,worker进程谁拿到锁,谁才将accept的fd加入到epoll队列中,其余的子进程拿不到锁,会将fd从epoll队列中移除,新链接到来也就不会致使全部子进程的epoll_wait被唤醒返回。socket

在处理事件的函数ngx_process_events_and_timers中,worker会尝试得到accept_mutex锁,同一时刻只有一个worker能够得到这把互斥锁。若是一个worker拿到了锁,就把监听的fd加入epoll队列,而且置NGX_POST_EVENTS标志位,意思是会优先处理accept事件,把其余全部事件放在accept后延后处理,由于在处理完accept事件后worker就能够马上释放互斥锁,这样尽可能减小锁的占用时间。函数

在获取accept_mutex锁前还有一个负载均衡的逻辑,若是worker的当前活动链接数超过最大可承受链接数的7/8,则表示发生过载,不会去争取锁。性能

相关文章
相关标签/搜索