zoukankan      html  css  js  c++  java
  • 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;
                    }
                }
            }
        }
    
    
  • 相关阅读:
    一致性哈系算法
    进程通信,线程通信,同步方式
    token的作用
    PHP与web 页面交互
    PHP !!
    Vue局部组件和全局组件
    vue父子组件之间的通信
    Spring Cloud 微服务架构学习笔记与示例
    feign中开启熔断的书写步骤
    使用springboot配置和注入数据源属性的方法和步骤
  • 原文地址:https://www.cnblogs.com/bewolf/p/11191616.html
Copyright © 2011-2022 走看看