zoukankan      html  css  js  c++  java
  • Nginx惊群处理

    惊群:是指在多线程/多进程中,当有一个客户端发生链接请求时,多线程/多进程都被唤醒,然后只仅仅有一个进程/线程处理成功,其他进程/线程还是回到睡眠状态,这种现象就是惊群。

    惊群是经常发生现在server端,父进程fork很多子进程,当有客户端有链接请求时,所有子进程都被唤醒,可是只有一个子进程处理请求,其他子进程就继续休眠。

    Nginx  处理集群的方法:

      ngx_postd_events:是监听套接口上的事件

      ngx_posted_accept_events:是新建连接事件(也就是监听套接口上发生的可读事件)

      ngx_accept_mutex_held:看是否拥有锁

      Nginx中统一时刻,监听套接口只可能被一个进程监控,并且在建立新连接时,通过获得锁,来确定那个子进程进行监控。当当前工作进程负载较小时,即当前活动连接数 < 最大可承受连接数的*7/8,就可以将监听套接口加入到自身的时间监控机制中,从而带来新的请求,如果当前进程的负载很大,则将该监听套接口从自身的事件中删除,避免带来的新的客户端的请求而带来更大的负载。

      关于锁,持锁者必须缩短自身拥有锁的事件,所以Nginx是将很多时间延迟到释放锁之后进行处理,把锁释放,尽量释放拥有锁的时间,让其他进程有机会获得锁。

      

     1 if (ngx_use_accept_mutex)
     2 {
     3          //
     4 当前的连接数是否超过最大可承受连接数的 7/8
     5         if (ngx_accept_disabled > 0) 
     6         {
     7             ngx_accept_disabled--;
     8         } 
     9         else
    10          {
    11     //获得锁
    12                 if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) 
    13                 {
    14                     return;
    15                 }
    16     //获得锁,表明新建连接后,将所有事件延后处理,先释放锁,是的拥有锁的事件最小化
    17                 if (ngx_accept_mutex_held) 
    18                 {
    19                         flags |= NGX_POST_EVENTS;
    20     } 
    21     else 
    22     {
    23                     //没有获得锁传给epoll_wait使得epoll_wait 使得返回时间剪短防止长时间连接没有返        //
    24         if (timer == NGX_TIMER_INFINITE|| timer > ngx_accept_mutex_delay)
    25                     {
    26                             timer = ngx_accept_mutex_delay;
    27                     }
    28             }
    29   }
    30 
    31        ngx_accept_disabled = ngx_cycle->connection_n / 8
    32  - ngx_cycle->free_connection_n;
    33 
    34 
    35     delta = ngx_current_msec;
    36 
    37     (void) ngx_process_events(cycle, timer, flags);
    38 
    39     delta = ngx_current_msec - delta;
    40 
    41     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
    42                    "timer delta: %M", delta);
    43 
    44 //新建链接缓存
    45     ngx_event_process_posted(cycle, &ngx_posted_accept_events);
    46 
    47 //释放锁
    48     if (ngx_accept_mutex_held) {
    49         ngx_shmtx_unlock(&ngx_accept_mutex);
    50     }
    51 
    52     if (delta) {
    53         ngx_event_expire_timers();
    54     }
    55     ngx_event_process_posted(cycle, &ngx_posted_events);
    56 /*
    57     此处释放锁并没有将监听套接字从时间监控机制中删除,在接下来的ngx_posted_events缓存事件时,互斥锁被另一个进程争取,并且把监听套接字加入到事件监听机制中,而同一时间,一个监听套接字被多个程序占有,因此进程在处理完ngx_posted_events后去争取锁,发现锁被其他进程占用而失败,所以将该监听套接口从自身的事件监听机制中删除,然后才进行事件监控。
    58 */
  • 相关阅读:
    第四章 springboot + swagger
    第三章 springboot + jedisCluster
    第二章 第二个spring-boot程序
    mac下的一些命令
    Redis(二十一):Redis性能问题排查解决手册(转)
    TreeMap升序|降序排列和按照value进行排序
    关于java集合类TreeMap的理解(转)
    Redis(二十):Redis数据过期和淘汰策略详解(转)
    Redis(十九):Redis压力测试工具benchmark
    try、finally代码块有无return时的执行顺序
  • 原文地址:https://www.cnblogs.com/chenyang920/p/5527078.html
Copyright © 2011-2022 走看看