Nginx中的惊群现象解决方法

xiaoxiao2021-02-28  43

*什么是惊群现象?Nginx中用了什么方法来避免这种问题的发生?本篇就解决这两个问题。。。→_→*

惊群现象的定义与危害

在Nginx中,每一个worker进程都是由master进程fork出来的。master进程创建socket后进行listen、bind操作,fork出来的worker继承了socket,调用accpet开始监听等待网络连接

如果这时有多个worker进程都在等待事件的发生。当事件发生时,这些worker进程被同时唤醒,但最终只有一个worker进程可以处理事件成功,其他的worker进程就会重新进入阻塞状态

当惊群现象发生时,内核会依次唤醒所有的worker进程,这种操作会导致系统在瞬时占用极大的资源,但最后却只有一个worker进程处理事件成功,这就造成了极大的资源浪费

Nginx中解决惊群现象的方法

Nginx中规定同一时刻只能有唯一一个的worker进程监听Web端口,这样就不会发生惊群了,此时新连接事件只能唤醒唯一正在监听端口的worker进程

源码剖析

ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle) { //使用worker进程间同步锁——ngx_accept_mutex,ngx_shmtx_trylock返回1表示成功获取锁,返回0表示获取锁失败。ngx_shmtx_trylock是非阻塞的,如果此时ngx_accept_mutex被其他worker进程占有,那么ngx_shmtx_trylock会立即返回 if (ngx_shmtx_trylock(&ngx_accept_mutex)) { ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "accept mutex locked"); //ngx_accept_mutex_held为1时表示当前worker进程已经获取到了锁,那么就立即返回 if (ngx_accept_mutex_held && ngx_accept_events == 0 && !(ngx_event_flags & NGX_USE_RTSIG_EVENT)) { return NGX_OK; } //将所有监听连接的读事件添加到当前的epoll等事件驱动模块中 if (ngx_enable_accept_events(cycle) == NGX_ERROR) { //如果将所有监听连接的读事件添加到当前的epoll等事件驱动模块中失败,那么就必须释放ngx_accept_mutex锁 ngx_shmtx_unlock(&ngx_accept_mutex); return NGX_ERROR; } //此时需要把ngx_accept_mutex_held置为1,方便本进程的其他驱动模块它已经获取到了锁 ngx_accept_events = 0; ngx_accept_mutex_held = 1; return NGX_OK; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "accept mutex lock failed: %ui", ngx_accept_mutex_held); //此时ngx_shmtx_trylock返回了0,表示获取ngx_shmtx_trylock锁失败。但是此时ngx_accept_mutex_held还为1,即当前worker进程还在占有ngx_accept_mutex锁,就说明有问题 if (ngx_accept_mutex_held) { //将所有监听连接的读事件从事件模块中移出 if (ngx_disable_accept_events(cycle) == NGX_ERROR) { return NGX_ERROR; } //没有获取到ngx_accept_mutex锁时,将ngx_accept_mutex_held置为0 ngx_accept_mutex_held = 0; } return NGX_OK; }

*本篇只分析了Nginx中如何保证不发生惊群现象的解决方法,后面其实还有worker进程何时释放ngx_accept_mutex锁的问题。。其超出了本篇的范围。。。就不在这里继续讨论了。。明天加油。。。→_→*

转载请注明原文地址: https://www.6miu.com/read-82616.html

最新回复(0)