perrynzhou

专注于系统组件研发

0%

nginx 的worker_process

nginx 的worker_process

nginx的配置worker_process

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[perrynzhou@perrynzhou-ubuntu ~/Debug/nginx-1.19.0/conf]$ cat nginx.conf 

#user nobody;
worker_processes 1;

events {
worker_connections 1024;
}


http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;


server {
listen 80;
server_name localhost;

location / {
root html;
index index.html index.htm;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

}

nginx 如何配置worker_process呢?

nginx中通过static ngx_command_t ngx_core_commands[]数组表示配置文件以及配置文件中的回调函数
1
2
3
4
5
6
{ ngx_string("worker_processes"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_set_worker_processes,
0,
0,
NULL },
worker_process 通过回调函数ngx_set_worker_processes设置nginx的进程数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
static char *
ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_str_t *value;
ngx_core_conf_t *ccf;

ccf = (ngx_core_conf_t *) conf;

if (ccf->worker_processes != NGX_CONF_UNSET) {
return "is duplicate";
}

value = (ngx_str_t *) cf->args->elts;

if (ngx_strcmp(value[1].data, "auto") == 0) {
//如果在 conf/nginx.conf 中配置 worker_processes auto;则会走这个逻辑
ccf->worker_processes = ngx_ncpu;
//ngx_cpu:会在 ngx_os_init 函数中初始化这个全局变量,ngx_ncpu = sysconf(_SC_NPROCESSORS_ONLN);获取CPU逻辑核
return NGX_CONF_OK;
}

ccf->worker_processes = ngx_atoi(value[1].data, value[1].len);

if (ccf->worker_processes == NGX_ERROR) {
return "invalid value";
}

return NGX_CONF_OK;
}

nginx 如何启动一个或者多个 worker_process?

  • 调用关系链
1
2
3
main->
ngx_master_process_cycle->
ngx_start_worker_processes
  • main:nginx入口函数
  • ngx_master_process_cycle:依据配置文件初始化worker_process和master process.同时提供nginx -h 列举出所有的命令操作实现,这里仅仅列举出来和master、worker进程相关的实现
    1
    2
    3
    4
    5
    6
    7
    8
    void ngx_master_process_cycle(ngx_cycle_t *cycle)
    {
    //fork进程作为master进程
    ngx_start_worker_processes(cycle, ccf->worker_processes,NGX_PROCESS_JUST_RESPAWN);

    //fork worker进程
    ngx_start_cache_manager_processes(cycle, 1);
    }
  • ngx_start_worker_processes:根据配置文件启动多个work_process.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
{

for (i = 0; i < n; i++) {
//ngx_worker_process_cycle 是每个work进程执行的函数
ngx_spawn_process(cycle, ngx_worker_process_cycle, (void *) (intptr_t) i, "worker process", type);
}
}
static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
{
ngx_int_t worker = (intptr_t) data;

ngx_uint_t i;
ngx_connection_t *c;

ngx_process = NGX_PROCESS_WORKER;
ngx_worker_process_init(cycle, worker);
ngx_setproctitle("worker process");
//忽略了其他的代码
for ( ;; ) {

if (ngx_exiting) {

c = cycle->connections;

for (i = 0; i < cycle->connection_n; i++) {

/* THREAD: lock */

if (c[i].fd != -1 && c[i].idle) {
c[i].close = 1;
c[i].read->handler(c[i].read);
}
}
}

}

ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,char *name, ngx_int_t respawn)
{
//
pid = fork();

switch (pid) {

case -1:
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"fork() failed while spawning \"%s\"", name);
ngx_close_channel(ngx_processes[s].channel, cycle->log);
return NGX_INVALID_PID;

case 0:
ngx_pid = ngx_getpid();
proc(cycle, data);
break;

default:
break;
}

}