菜鸟nginx源码剖析架构篇(二) nginx进程模型
-
Author:Echo Chen(陈斌)
-
Email:chenb19870707@gmail.com
-
Date:Nov 17th, 2014
1.nginx进程模型
nginx采用的是多进程模型,典型的master-worker方式,采用一个master process(监控进程,也叫做主进程)和多个woker process(工作进程)的设计方式,此外,还有1个可选的chache manager和 1 个可选的cache loader进程。
-
(1)利用多核系统的并发处理能力;
-
(2)负载均衡;
-
(3)管理进程会负责监控工作进程的状态,并负责管理其行为。
2. master-worker 启动流程
启动nginx的主进程将充当master进程,而由主进程fork()出来的子进程则充当工作进程。nginx也可以单进程模型执行,在这种进程模型下,主进程就是工作进程,没有监控进程。
Nginx的核心进程模型框图如下:
-
-
3.master进程是如何工作的
监控进程充当整个进程组与用户的交互接口,同时对进程进行监护。它不需要处理网络事件,不负责业务的执行,只会通过管理worker进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。
其工作流程如下图,它首先fork出worker进程,然后进入for循环,在每一帧循环中调用sigsupend挂起等待信号,如果收到信号,就处理信号,改变响应的标志位,然后根据标志位做出相应的操作。
master进程的标志位有如下7个:
1: sig_atomic_t ngx_reap;
2: sig_atomic_t ngx_terminate;
3: sig_atomic_t ngx_quit;
4: sig_atomic_t ngx_reconfigure;
5: sig_atomic_t ngx_reopen;
6: sig_atomic_t ngx_change_binary;
7: sig_atomic_t ngx_noaccept;
每个标志与信号位的及作用的对应关系如下表:这样,master进程的运行情况如下图:
下面看一下核心代码:
3.1 master进程住循环函数 ngx_master_process_cycle
1: void
2: ngx_master_process_cycle(ngx_cycle_t *cycle)
3: {
4: char *title;
5: u_char *p;
6: size_t size;
7: ngx_int_t i;
8: ngx_uint_t n, sigio;
9: sigset_t set;
10: struct itimerval itv;
11: ngx_uint_t live;
12: ngx_msec_t delay;
13: ngx_listening_t *ls;
14: ngx_core_conf_t *ccf;
15:
16: //设置屏蔽信号
17: sigemptyset(&set);
18: sigaddset(&set, SIGCHLD);
19: sigaddset(&set, SIGALRM);
20: sigaddset(&set, SIGIO);
21: sigaddset(&set, SIGINT);
22: sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));
23: sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));
24: sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL));
25: sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));
26: sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
27: sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));
28:
29: if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
30: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
31: "sigprocmask() failed");
32: }
33:
34: sigemptyset(&set);
35:
36:
37: size = sizeof(master_process);
38:
39: for (i = 0; i < ngx_argc; i++) {
40: size += ngx_strlen(ngx_argv[i]) + 1;
41: }
42:
43: title = ngx_pnalloc(cycle->pool, size);
44:
45: p = ngx_cpymem(title, master_process, sizeof(master_process) - 1);
46: for (i = 0; i < ngx_argc; i++) {
47: *p++ = ' ';
48: p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size);
49: }
50:
51: ngx_setproctitle(title);
52:
53:
54: ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
55:
56: //其中包含了fork产生子进程的内容
57: ngx_start_worker_processes(cycle, ccf->worker_processes,
58: NGX_PROCESS_RESPAWN);
59: //Cache管理进程与cache加载进程的主流程
60: ngx_start_cache_manager_processes(cycle, 0);
61:
62: ngx_new_binary = 0;
63: delay = 0;
64: sigio = 0;
65: live = 1;
66:
67: for ( ;; ) { //循环
68: if (delay) {
69: if (ngx_sigalrm) {
70: sigio = 0;
71: delay *= 2;
72: ngx_sigalrm = 0;
73: }
74:
75: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
76: "termination cycle: %d", delay);
77:
78: itv.it_interval.tv_sec = 0;
79: itv.it_interval.tv_usec = 0;
80: itv.it_value.tv_sec = delay / 1000;
81: itv.it_value.tv_usec = (delay % 1000 ) * 1000;
82:
83: if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
84: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
85: "setitimer() failed");
86: }
87: }