nginx源代码分析 - 启动(八) 避免epoll_wait惊群

来源:互联网 发布:美国反对美国 知乎 编辑:程序博客网 时间:2024/04/26 22:22

nginx使用epoll来处理accept事件,所有会有epoll惊群问题,


ngx_accept_disabled = ngx_cycle->connection_n / 8 - ngx_cycle->free_connection_n; 这个变量是禁用accept,就是现在的连接数比较多
ngx_use_accept_mutex全局变量为1,才开启避免惊群的现象

ngx_use_accept_mutex = 1;的条件是ccf->master && ccf->worker_processes > 1 && ecf->accept_mutex
对应的配置是在event block下面accept_mutex on;

在ngx_event_process_init函数中如果ngx_use_accept_mutex开启,则不会将fd加入本worker进程的epoll
在worker进程的大循环,ngx_process_events_and_timers函数在,如果ngx_use_accept_mutex开启,则所有进程都会去得到ngx_accept_mutex
得到的把listen的fd加到本进程的epoll中,其他的都移除。

这个锁是放在共享内存上的
cl = 128;/* cl should be equal to or greater than cache line size */
size = cl            /* ngx_accept_mutex */
           + cl          /* ngx_connection_counter */
           + cl;         /* ngx_temp_number */

NGX_HAVE_MAP_ANON
shm->addr = (u_char *) mmap(NULL, shm->size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

全局变量ngx_accept_mutex_ptr保存了这一地址,这是个内核地址,所有进程都可以访问,也就成共享内存了
ngx_shmtx_sh_t只有16字节,却分配了128字节
全局变量ngx_accept_mutex->lock = &addr->lock
全局变量是指每个进程的,但是每个进程的这个变量都指向内核同一地址
(gdb) p  ngx_accept_mutex->lock
$1 = (ngx_atomic_t *) 0x7ffff7ff5000
(gdb) p  *ngx_accept_mutex->lock
$2 = 0

(void) ngx_atomic_cmp_set(ngx_connection_counter, 0, 1); 设置ngx_connection_counter = 1
           
锁的名字/home/liuwb/Desktop/code/nginx-code/logs/nginx.lock.accept
*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid) 如果mtx->lock == 0,将mtx->lock的值设为ngx_pid,返回1
将ngx_pid的值设在mtx->lock中,是这个worker的pid

ngx_accept_events = 0;
ngx_accept_mutex_held = 1;表示该进程不会拿到锁


0 0
原创粉丝点击