nginx惊群问题

什么是nginx惊群问题?

了解惊群问题首先要了解下nginx进程部署架构:nginx进程主要是一个主进程(master)和多个工作进程(worker)。master进程并不处理网络请求,主要负责初始化和调度工作进程,如加载配置、启动工作进程 ,升级等,worker进程用来处理网络请求,并且一个连接的多个阶段处理都在同一个worker中进行。既然是多个worker同时等待同一个socket事件,当这个事件发生时,所有worker同时唤醒,但最终只能有一个进程能建立成功,其他进程都会失败,造成了资源的浪费。

nginx解决惊群到方法

简单总结就是同一时刻保证只有一个worker在监听。那么这个是如何做到呢?其实也很简单,增加一个ngx_use_accept_mutex锁,各个worker在监听socket事要先拿到这个锁,而同一时刻保证只有一个worker拿到。

很多操作系统已经在epoll阶段解决了这个问题,为什么nginx还要做?

1、跨平台,有些不支持

2、实现各个worker负载均衡

为了使各个worker上的连接达到负载均衡,定义了全局变量ngx_accept_disabled,其为值为连接总数的1/8-剩余连接数,即初始化时为负值,拿ngx_use_accept_mutex锁的时候,会判断该值是否为正,如果为正就建立连接而是将值减1,也就是说在worker上连接数目达到规格的7/8时才开始负载均衡。

ngx_accept_disabled = ngx_cycle->connection_n / 8
                              - ngx_cycle->free_connection_n;
void
ngx_process_events_and_timers(ngx_cycle_t *cycle)
{
    。。。
    //ngx_use_accept_mutex表示是否需要通过对accept加锁来解决惊群问题。当nginx worker进程数>1时且配置文件中打开accept_mutex时,这个标志置为1
    if (ngx_use_accept_mutex) {
            //ngx_accept_disabled表示此时满负荷,没必要再处理新连接了,我们在nginx.conf曾经配置了每一个nginx worker进程能够处理的最大连接数,当达到最大数的7/8时,ngx_accept_disabled为正,说明本nginx worker进程非常繁忙,将不再去处理新连接,这也是个简单的负载均衡
        if (ngx_accept_disabled > 0) {
            ngx_accept_disabled--;
 
        } else {
                //获得accept锁,多个worker仅有一个可以得到这把锁。获得锁不是阻塞过程,都是立刻返回,获取成功的话ngx_accept_mutex_held被置为1。拿到锁,意味着监听句柄被放到本进程的epoll中了,如果没有拿到锁,则监听句柄会被从epoll中取出。
            if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
                return;
            }
 
               //拿到锁的话,置flag为NGX_POST_EVENTS,这意味着ngx_process_events函数中,任何事件都将延后处理,会把accept事件都放到ngx_posted_accept_events链表中,epollin|epollout事件都放到ngx_posted_events链表中
            if (ngx_accept_mutex_held) {
                flags |= NGX_POST_EVENTS;
 
            } else {
                    //拿不到锁,也就不会处理监听的句柄,这个timer实际是传给epoll_wait的超时时间,修改为最大ngx_accept_mutex_delay意味着epoll_wait更短的超时返回,以免新连接长时间没有得到处理
                if (timer == NGX_TIMER_INFINITE
                    || timer > ngx_accept_mutex_delay)
                {
                    timer = ngx_accept_mutex_delay;
                }
            }
        }
    }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券