1. 程式人生 > >啟動(八) 避免epoll_wait驚群

啟動(八) 避免epoll_wait驚群

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;表示該程序不會拿到鎖