38

Nginx源码阅读笔记-Master Woker进程模型

 5 years ago
source link: https://www.codedump.info/post/20190131-nginx-master-worker/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

master进程

Nginx采用的模型是master-worker模型,即:

  • 由master进程负责创建worker进程,以及监控worker进程的情况,如需要更新配置的情况下发消息给worker进程重新加载配置等。
  • master进程负责具体网络事件。

将里面核心的流程和函数抽取出来,如下图所示:

ueIj63V.png!web

  • master进程的主循环在函数ngx_master_process_cycle中,主要负责:
    • 调用ngx_start_worker_processes函数创建worker子进程。
    • 监控各种信号量的变化做处理,比如需要停止进程、重新加载配置等。
  • master进程最终会调用函数ngx_spawn_process函数来创建出worker子进程:
    • 使用共享内存创建出用于master-worker进程之间通信的channel。
    • fork出子进程之后,进入worker进程的主函数ngx_worker_process_cycle。

以下列举出几个相关的信号量:

信号 对应全局变量 处理 QUIT ngx_quit 优雅关闭整个Nginx服务 TERM或者INT ngx_terminate 强制关闭Nginx服务 USR1 ngx_reopen 重新打开文件 WINCH ngx_noaccept 所有worker进程不再接受新的连接,相当于给子进程发送QUIT信号 USR2 ngx_change_binary 平滑升级到新的Nginx二进制文件 HUP ng_reconfigure 重新加载配置文件 CHLD ngx_reap 需要监控所有子进程

worker进程

worker进程的函数入口在ngx_worker_process_cycle中,其主要做的工作分为两部分:

  • 调用ngx_process_events_and_timers处理IO事件以及定时器事件。
  • 判断ngx_terminate、ngx_quit、ngx_reopen这几个变量是否被置位来做相应的处理。

下面主要谈网络IO事件的处理,即ngx_process_events_and_timers函数。

先来介绍几个与接收连接相关的全局变量:

  • ngx_use_accept_mutex:由配置项accept_mutex配置,表示是否需要使用accept锁,只有抢到该锁的worker才允许接收新的连接。
  • ngx_accept_mutex_delay:由配置项accept_mutex_delay配置,在开启accept_mutex的情况下,一个worker进程在抢不到accept锁的情况下,最长多少时间才重新接收新的连接。
  • ngx_accept_disabled:值为ngx_cycle->connection_n / 8 - ngx_cycle->free_connection_n,可以看到当链接数量到nginx.conf中配置的worker_connections的7/8以上时,这个变量ngx_accept_disabled为正数,此时不会接收新的连接,直到该值小于等于0为止。
  • ngx_accept_mutex_held:表示是否抢到了accept锁,只有抢到的才能接收新连接。

具体来看看ngx_process_events_and_timers函数中与接收连接相关的逻辑,伪代码如下:

如果开启了accept_mutex配置:
  如果当前ngx_accept_disabled大于0,表示不能接收新的连接,直接返回。
  否则尝试获取accept mutex。
  如果获取accept mutex锁成功:
    将调用事件轮询函数的标志位加上NGX_POST_EVENTS标志
  如果获取失败:
    调用事件轮询函数的事件参数不得超过ngx_accept_mutex_delay值。

  调用ngx_process_events函数处理轮询事件

  调用ngx_event_process_posted(cycle, &ngx_posted_accept_events)函数处理accept事件

  如果前面拿到了accept mutex锁,则释放这个锁,好让其他worker也有机会接收新的连接

  调用ngx_event_expire_timers处理定时器事件

  调用ngx_event_process_posted(cycle, &ngx_posted_events);函数处理除了accept事件以外的其他post事件

在ngx_process_events处理函数中,当传入的flags有NGX_POST_EVENTS标志时,意味着并不马上在这个函数中调用事件的回调函数进行处理,而是放在一个队列中,回头在后面的ngx_event_process_posted函数中再进行处理。

而这里的队列分为两类:

  • ngx_posted_accept_events用于存放接收新连接事件。
  • ngx_posted_events用于存放除了accept之外的其他事件。

这样的做法,是为了将接收新连接的事件优先级放在其他IO事件以及定时器事件之前。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK