Nginx 进阶

Nginx 请求处理流程

Nginx 的请求处理流程大体是这样的:接收到 WEB、EMAIL、TCP 流量后,因为 Nginx 采用的非阻塞的事件驱动处理引擎,所以会有传输层状态机处理 TCP 流量,HTTP 状态机处理 WEB 流量,MAIL 状态机处理 EMAIL 流量,然后进行静态资源访问,如果是反向代理还能加入磁盘缓存,当分配的内存不足以完全缓存文件内容时,例如 sendfile 等大文件时,会退化成阻塞的磁盘调用,所以还会使用线程池处理磁盘阻塞调用,对于每一个处理完成的请求,会记录 Access 访问日志和 Error 错误日志,Nginx 作为负载均衡使用时,可以把请求通过协议机传输到后面的服务器。

Nginx 架构

Nginx 可以分为单进程和多进程模式,单进程一般作为调试开发使用,在生产环境一般用多进程。

Nginx 多进程模式,有一个主进程和其他子进程(包括 Worker 进程 和 cache 相关进程:Cache manager、Cache loader)。主进程的主要工作是加载和执行配置文件,并且驻留子进程。子进程用来作为实际的请求处理。Nginx 采取基于事件的模型和 OS 依赖的机制,在多个子进程之间高效的分配请求。子进程的个数会直接写在配置文件中,并且对于给定的配置可以是固定的,也可以根据可用的 CPU 核数自动进行调整。缓存相关的内容是各进程共享的,反向代理时,Cache manager 进程管理上游的缓存,Cache loader 进程载入上游的缓存。

Nginx 进程管理:信号

Nginx 的多进程通信是使用的共享内存方式,Nginx 的进程管理使用的是信号。

Master 进程

监控 Worker 进程

Master 进程会监控 Worker 进程有没有发来的 CHLD 信号,Linux 系统规定,当子进程终止时,会向父进程发送 CHLD 信号。当 Worker 进程因为某些原因报错终止时,会向 Master 进程发送 CHLD 信号,Master 进程接收到信号后,会拉起一个新的 Worker 进程。

管理 Worker 进程

Master 进程会接收到一些信号来管理 Worker 进程。

既可以使用 Nginx 命令行,也可以使用 kill 指令的方式接收的信号有以下几种:

  • TERM,INT 立刻停止 Nginx 进程,对应 nginx -s stop

  • QUIT 优雅停止,对应 nginx -s quit

  • HUP 重新载入配置文件,对应 nginx -s reload

  • USR1 重新打开日志文件,做日志切割,对应 nginx -s reopen

以上几种信号用 Nginx 命令行可以起到同样的作用是因为,Nginx 在启动时,一般会默认在 Nginx 安装目录的 logs 文件夹下 nginx.pid 中记录 Nginx 的 Master 进程 pid,在执行 nginx -s 命令时,这个命令行工具会向 nginx.pid 记录的 pid 发送相应的信号。

只能使用 kill 指令的方式接收的信号:

  • USR2

  • WINCH

Worker 进程

Worker 进程也可以接收一些信号,只能使用 kill + 进程 id 的方式:

  • TERM,INT

  • QUIT

  • USR1

  • WINCH

通常我们不直接对 Worker 进程发送信号,因为规范的方式是通过 Master 进程来管理 Worker 进程

Nginx reload 流程

  1. 向 Master 进程发送 HUP 信号(reload 命令)

  2. Master 进程校验配置语法是否正确

  3. Master 进程打开新的监听端口(如果有新端口的话,因为子进程的端口会继承父进程的端口)

  4. Master 进程用新配置启动新的 Worker 子进程

  5. Master 进程向老 Worker 子进程发送 QUIT 信号

  6. 老 Worker 子进程关闭监听句柄,处理完当前连接后结束进程(为了避免老 Worker 子进程长时间存在,可以设置 worker_shutdown_timeout 超时时间)

Nginx 热升级流程

  1. 将旧 Nginx 文件换成新 Nginx 文件(注意备份)

  2. 向 master 进程发送 USR2 信号

  3. master 进程修改 pid 文件名,加后缀 .oldbin

  4. master 进程用新 Nginx 文件启动新 master 进程

  5. 向老 master 进程发送 QUIT 信号,关闭老 master 进程

  6. 回滚:向老 master 发送 HUP,向新 master 发送 QUIT

worker 进程优雅关闭(quit)

  1. 设置定时器 worker_shutdown_timeout

  2. 关闭监听句柄

  3. 关闭空闲连接

  4. 在循环中等待全部连接关闭(时间可能会较长,当超过 worker_shutdown_timeout 设置的时间,worker 进程会把剩下的连接直接关闭)

  5. 退出进程

共享内存

跨 worker 进程通信的关键是共享内存,官方 Nginx 模块使用了共享内存的有以下几个:

  • ngx_http_lua_api

  • rbtree 数据结构

    • ngx_stream_limit_conn_module

    • ngx_http_limit_conn_module

    • ngx_stream_limit_req_module

    • http cache 相关

      • ngx_http_file_cache

      • ngx_http_proxy_module

      • ngx_http_scgi_module

      • ngx_http_uwsgi_module

      • ngx_http_fastcgi_module

    • ssl 相关

      • ngx_http_ssl_module

      • ngx_mail_ssl_module

      • ngx_stream_ssl_module

  • 单链表数据结构

    • ngx_http_upstream_zone_module

    • ngx_stream_upstream_zone_module

Last updated

Was this helpful?