本文主要简要介绍Nginx中关于套接字的继承,这里提到的继承不是指worker进程继承master进程的监听套接字,而是指启动master进程时,master继承父进程的监听套接字。
继承的方式
1、master进程在main函数中调用ngx_add_inherited_sockets函数判断是否需要继承父进程的监听套接字。若没有需继承的套接字则返回,否则继续。
2、ngx_add_inherited_sockets中获取环境变量"NGINX",若该环境变量非空,则取出该环境变量。
3、环境变量"NGINX"的内容为父进程的文件描述符(监听套接字),格式为:fd1:fd2:fd3; 冒号分隔描述符,最后加上一个分号。
4、master取出需要继承的套接字,并为其创建一个ngx_listening_t结构体,用来保存该套接字相关的参数。
5、ngx_add_inherited_sockets中取出所有需要继承的监听套接字后,调用ngx_set_inherited_sockets函数来获取每一个需要继承的套接字相关的参数,将这些参数保存至对应的ngx_listening_t结构体。
可使用场景:用于nginx的平滑升级,master设置环境变量"NGINX"后,先调用fork,在调用exec启动新的master进程。
无论是调用exec还是fork,子进程均可以继承父进程的文件描述符。
具体代码如下:
static ngx_int_t
ngx_add_inherited_sockets(ngx_cycle_t *cycle)
{
u_char *p, *v, *inherited;
ngx_int_t s;
ngx_listening_t *ls;
inherited = (u_char *) getenv(NGINX_VAR);
if (inherited == NULL) {
return NGX_OK;
}
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
"using inherited sockets from \"%s\"", inherited);
if (ngx_array_init(&cycle->listening, cycle->pool, 10,
sizeof(ngx_listening_t))
!= NGX_OK)
{
return NGX_ERROR;
}
for (p = inherited, v = p; *p; p++) {
if (*p == ':' || *p == ';') {
s = ngx_atoi(v, p - v);
if (s == NGX_ERROR) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
"invalid socket number \"%s\" in " NGINX_VAR
" environment variable, ignoring the rest"
" of the variable", v);
break;
}
v = p + 1;
ls = ngx_arr