目录

  • 进程结构图
  • 信号量管理 Linux 的信号量管理机制利用信号量管理 Nginx 进程
  • 配置文件重载原理

C/C++ Linux 服务器开发高级架构学习视频点击:C/C++Linux服务器开发/Linux后台架构师-学习视频教程

进程结构图

Nginx 是多进程结构,多进程结构设计是为了保证 Nginx 的高可用高可靠,包含:

  • master 进程:父进程,负责 worker 进程的管理
  • worker 进程:子进程,worker 进程一般配置与服务器 CPU 核数相同,worker 进程用来处理具体请求。
  • cache 进程:也是子进程,包括 cache manager 和 cache loader 进程,主要是反向代理做缓存使用。

注:多进程相对于多线程之所以能够保证高可用与高可靠是因为进程间地址空间是独立的,进程间的任务不会相互影响,相对多线程更加耗费 CPU 资源。而多线程共享一个进程的地址空间,其中一个线程任务失败会影响到其它线程任务。

nginx配置文件重载 nginx重载命令_nginx配置文件重载

图 3-1 Nginx 进程结构图

假设我们的 Nginx 服务的用户是 nginx,我们可以使用如下命令查看当前运行的 Nginx 服务的 master 进程和 worker 进程,而且可以看到 4 个 worker 进程的父进程 ID 都是 master 的进程 ID(1325)。

[root@master ~]# ps -ef | grep nginx | grep -v grep | grep -v php-fpm
root       1325      1  0 11:28 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx      1332   1325  0 11:28 ?        00:00:00 nginx: worker process
nginx      1334   1325  0 11:28 ?        00:00:00 nginx: worker process
nginx      1335   1325  0 11:28 ?        00:00:00 nginx: worker process
nginx      1336   1325  0 11:28 ?        00:00:00 nginx: worker process

复制代码

nginx配置文件重载 nginx重载命令_nginx配置文件重载_02

图 3-2 一个 master 进程与四个 worker 子进程

我们可以通过 lsof -i:nginx 端口号 来查看我们的 master 和 worker 进程。

[root@master ~]# lsof -i:80
COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nginx   1325  root    6u  IPv4  22282      0t0  TCP *:http (LISTEN)
nginx   1332 nginx    6u  IPv4  22282      0t0  TCP *:http (LISTEN)
nginx   1334 nginx    6u  IPv4  22282      0t0  TCP *:http (LISTEN)
nginx   1335 nginx    6u  IPv4  22282      0t0  TCP *:http (LISTEN)
nginx   1336 nginx    6u  IPv4  22282      0t0  TCP *:http (LISTEN)

复制代码

信号量管理

Linux 的信号量管理机制

信号是进程间通信方式之一,典型用法是:终端用户输入中断命令,通过信号机制停止一个程序的运行。

我们可以通过给进程发送信号来管理我们的进程,kill -l 命令可以查看 linux 支持的信号量

nginx配置文件重载 nginx重载命令_linux_03

linux 信号量

一共有 64 号信号量,主要需要弄清如下几个:

kill -1 $PID:(SIGHUP)重新加载进程,对于与终端脱离关系的守护进程,这个信号用于通知它重新读取配置文件;
kill -2 $PID:(SIGINT)中断(通 Ctrl+C);
kill -3 $PID:(SIGQUIT)从键盘输入的退出(ctrl-\);
kill -9 $PID:(SIGKILL)立即杀死进程,无论当前程序处于什么状态;
kill -10 $PID:(SIGUSR1)$USR1 和 $USR2 都是留给用户自定义的信号量;
kill -12 $PID:($IGUSR2)
kill -15 $PID:(SIGTERM)正常停止一个进程;
kill -17 $PID:(SIGCHLD)父子进程通信的信号量,父进程可以 fork()出很多子进程,子进程挂掉会给父进程发送信号;

kill 可将指定的信息送至程序。预设的信息为 SIGTERM(15),可将指定程序终止。若仍无法终止该程序,可使用 SIGKILL(9) 信息尝试强制删除程序。程序或工作的编号可利用 ps 指令或 jobs 指令查看。

kill -l # 查看所有能够支持的信号
kill PID
# 杀死一个进程
kill 1024
# 杀死多个进程 进程号之间用空格隔开
kill 1024 2048
# kill -9 表示立即强制结束进程
kill -9 1024

复制代码

注:Ctrl+C:停止终端中正在运行的进程,Ctrl+C 可以比较有好地中止终端中正在运行的程序(进程)

关于 C/C++ Linux 后端开发网络底层原理知识 点击 后端开发学习资料 获取,内容知识点包括 Linux,Nginx,ZeroMQ,MySQL,Redis,线程池,MongoDB,ZK,Linux 内核,CDN,P2P,epoll,Docker,TCP/IP,协程,DPDK 等等。

nginx配置文件重载 nginx重载命令_nginx配置文件重载_04

利用信号量管理 Nginx 进程

管理 Nginx 进程可以这些方式:master 进程、worker 进程、命令行

使用信号量管理 master 和 worker(不推荐使用发送信号量的方式来管理 worker 进程,worker 进程应该交给 master 进程来管理和维护)。

Master 进程

  • 监控 worker 进程 CHLD
  • 管理 worker 进程
  • 接收信号 TERM、INTQUITHUPUSR1USR2WINCH

示例:

通过 kill 命令杀死 master 进程

kill -s SIGTERM 1325

复制代码

通过 kill 命令让 Nginx 重新读取文件,这样会关闭就得 worker 进程,生成新的 worker 进程,master 进程(ID)依旧保持不变

kill -s SIGHUP 1325

复制代码

Worker 进程

  • 接收信号 TERM、INTQUITUSR1WINCH
  • 虽然可以,但是不推荐使用信号量方式直接管理 worker 进程,worker 进程应该交给 master 进程来管理和维护

示例:

使用 kill 命令杀死一个 worker 进程,这样会杀死一个 worker 进程,linux 会杀掉的 worker 进程的父进程(master 进程)发送 SIGCHLD 信号量,所以 master 进程监测到我们某一个子进程可能出了问题,会启动一个新的 worker 进程,维护 worker 进程的数量。

kill -s SIGTERM 1332

复制代码

命令行

  • reload:HUP
  • reopen:USR2
  • stop:TERM
  • quit:QUIT

可以使用 nginx -h 查看帮助命令

[itbsl@master ~]$ nginx -h
nginx version: nginx/1.18.0
Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]


Options:
  -?,-h         : this help
  -v            : show version and exit
  -V            : show version and configure options then exit
  -t            : test configuration and exit
  -T            : test configuration, dump it and exit
  -q            : suppress non-error messages during configuration testing
  -s signal     : send signal to a master process: stop, quit, reopen, reload
  -p prefix     : set prefix path (default: /usr/local/nginx-1.18.0/)
  -c filename   : set configuration file (default: conf/nginx.conf)
  -g directives : set global directives out of configuration file

复制代码

参数说明:

  • -?,-h:查看帮助
  • -v:查看 Nginx 版本
  • -V:查看 Nginx 版本和编译选项
  • -t:检查配置文件语法是否正确
  • -T:检查配置文件语法是否正确,并打印
  • -q:在检查配置文件时不显示非错误消息
  • -s:给 master 进程发送信号,可以发送:stop、quit、reopen、reload
  • -c:指定配置文件
  • -g:设置配置文件之外的全局指令

配置文件重载原理

我们知道了可以通过给 nginx 的 master 进程发送 SIGHUP 信号,或者使用 nginx -s reload 命令来达到重新载入配置文件,从而使 nginx 平滑升级。那我们执行这样一个命令之后,对 nginx 本身来说背后发生了什么事情呢,它是如何保证新老请求如何平滑过渡的?

reload 重载配置文件的流程

  1. 向 master 进程发送 HUP 信号(reload 命令)
  2. master 进程检查配置语法是否正确
  3. master 进程打开监听端口(在修改配置文件的端口情况下,可能)
  4. master 进程使用新的配置文件启动新的 worker 子进程
  5. master 进程向老的 worker 子进程发送 QUIT 信号
  6. 旧的 worker 进程关闭监听句柄,处理完当前连接后关闭进程

如果用图示来描述的话大概如下图所示

nginx配置文件重载 nginx重载命令_nginx配置文件重载_05

nginx -s reload

图示解析:

1.左边绿色的状态是执行 nginx -s reload 命令之前的状态,按照我个人主机的配置时一个 master 进程和 4 个 worker 子进程。

2.为了模拟执行 nginx -s reload 命令后原来的 worker 进程会处理完请求后再被杀掉,我模拟一个需要很久才能处理完任务并响应的接口,是的,我在代码里 sleep 15 秒,也就是说这个接口响应需要 15 秒,时间弄长点方便我们来观察中间态,注意,在执行 reload 命令前请求该接口

<?php
    sleep(15);
    echo json_encode(['msg' => 'hello world']);die();

复制代码

3.我们已经知道了 master 进程会把任务交给 worker 子进程处理,目前只有一个任务,所以当前只需要一个 worker 进程需要处理任务。

4.执行 reload 命令,master 进程会创建 4 个(与你配置有关)新的 worker 进程(我上图中的黄色 worker 进程),关闭掉旧的空闲 worker 进程(绿色 worker 进程),而正在处理请求的旧 worker 进程不会立即关闭,而是会等请求处理完毕就关闭。

5.剩下的最后一个旧 worker 进程任务处理完毕也被关掉,最后剩下的都是使用新 nginx.conf 配置产生的新 worker 进程,可以看下面的这张图,那个处于 is shutting down 的旧 worker 进程就是因为处理上面 sleep 15 秒的任务接口还没处理完毕,所以依然能够被看到。

nginx配置文件重载 nginx重载命令_java_06