只有打开了accept_mutex锁,才可以解决“惊群”问题。何谓“惊群”?就像上面说过的那样,master进程开始监听Web端口,fork出多个worker子进程,这些子进程开始同时监听同一个Web端口。一般情况下,有多少CPU核心,就会配置多少个worker子进程,这样所有的worker子进程都在承担着Web服务器的角色。在这种情况下,就可以利用每一个CPU核心可以并发工作的特性,充分发挥多核机器的“威力”。但下面假定这样一个场景:没有用户连入服务器,某一时刻恰好所有的worker子进程都休眠且等待新连接的系统调用(如epoll_wait),这时有一个用户向服务器发起了连接,内核在收到TCP的SYN包时,会激活所有的休眠worker子进程,当然,此时只有最先开始执行accept的子进程可以成功建立新连接,而其他worker子进程都会accept失败。这些accept失败的子进程被内核唤醒是不必要的,它们被唤醒后的执行很可能也是多余的,那么这一时刻它们占用了本不需要占用的系统资源,引发了不必要的进程上下文切换,增加了系统开销。
也许很多操作系统的最新版本的内核已经在事件驱动机制中解决了“惊群”问题,但Nginx作为可移植性极高的Web服务器,还是在自身的应用层面上较好地解决了这一问题。既然“惊群”是多个子进程在同一时刻监听同一个端口引起的,那么Nginx的解决方式也很简单,它规定了同一时刻只能有唯一一个worker子进程监听Web端口,这样就不会发生“惊群”了,此时新连接事件只能唤醒唯一正在监听端口的worker子进程。
网友评论