第一章【基石与起源】—— 编译、安装与配置

第二节目录

一、环境准备与核心依赖

本节以 nginx-1.28.0 stable 为例,编译平台为 Rocky Linux 9。

环境准备

Nginx 源码包的准备:

核心依赖

构建工具:

  • C 编译器:Linux(gcc、clang)、Windows(MSVC)、MacOS(clang)。不推荐在 Windows 上进行源码构建,生产环境推荐在 Linux 上进行构建,开发或测试可在 MacOS上进行构建。如果非要在 Windows 上进行构建,推荐使用 VS(MSVC)进行,或者直接在 WSL 子系统的 Linux 平台上构建运行。

  • make 构建工具等:Linux 和 MacOS 都是通过 make 进行构建(配置 ./configure 文件构建),Windows 上通过 nmake 进行构建(配置 makefile.msvc 文件构建)。

  • 执行如下命令安装编译环境:

    bash 复制代码
    dnf install -y gcc automake autoconf libtool make

    automake、autoconf、libtool 可安装可不安装,nginx 构建时不依赖它们,但为了预防意料之外的情况发生,推荐安装。

核心依赖:

  • pcre 依赖库:此库的主要作用是提供正则表达式的支持,这是 nginx 能够实现基于内容的路由、重写和匹配功能的核心所在。此库在 rewrite 模块和 HTTP 核心模块中都需被用到;

  • zlib 依赖库:此库的主要作用是提供 HTTP 响应内容的即时压缩;

  • openssl 依赖包:此包的核心作用是提供 SSL/TLS 协议支持,使 nginx 能够处理和加密客户端与服务器之间的通信,赋予了 nginx 实现 HTTPS 的能力。

    如果不启用 HTTPS 或 rewrite,理论上可不装 openssl 或 pcre,但强烈推荐全部装上,避免后续功能受限。

  • 执行如下命令安装依赖包:

    bash 复制代码
    dnf install -y pcre pcre-devel zlib zlib-devel openssl openssl-devel

注意事项:源码编译安装 nginx(或其他 C/C++ 软件)时,必须安装 xx-devel(rhel 系)或 xx-dev(debian 系)这类"开发包",不能只装 xx(运行时库),否则 ./configure 会直接报错。因为编译过程需要通过头文件知道函数接口、通过库文件链接符号等操作,而 xx-devel / xx-dev 等开发包才提供了头文件、静态库和链接等信息。

二、NGINX 安装

源码编译安装

将 nginx-1.28.0 解压后,可以看到如下目录结构:

nginx-1.28.0 目录结构

名称 含义
auto 包含 nginx 的自动配置脚本文件,用于在不同操作系统和环境下检查系统特性、库文件和依赖项,并生成编译所需的 makefile 文件
CHANGES.ru 俄文版更新记录和版本历史记录
conf 存放 nginx 的默认配置文件 模板,如 nginx.conf 默认模板就在这里
contrib 包含一些贡献的附加工具或脚本,如用于在不同操作系统上启动/停止 nginx 的脚本等
html 存放默认 Web 页面文件,如默认的 index.html 等
man nginx 帮助手册
SECURITY.md 安全政策文件,说明了如何负责任的报告 nginx 中的安全漏洞,以及项目组处理安全问题的方式
CHANGES 更新记录和版本历史记录
CODE_OF_CONDUCT.md 行为准则文件,定义了参与 nginx 社区(如提交补丁、报告 Bug 等)应遵守的基本规范和期望行为
configure shell 总脚本,运行它会根据你提供的参数(如模块、安装路径等)和系统环境,在 auto 目录的帮助下生成所需的 makefile
CONTRIBUTING.md 贡献指南文件,说明了如何向 nginx 项目贡献代码、文档或其他资源,通常包括提交补丁的格式和流程
LICENES 开源许可证
README.md 项目说明文件
src 源码目录

编译准备阶段,需要知道各类编译选项的含义和用途:

安装目录配置选项 含义及用途 默认值
--prefix=xxx 设置主安装目录,所有其他相对路径(如配置、日志、HTML 目录)都将基于此路径 /usr/local/nginx
--sbin-path=xxx 指定主程序的可执行文件的路径 nginx/sbin/nginx
--conf-path=xxx 指定 nginx.conf 配置文件的路径 nginx/conf/nginx.conf
--error-log-path=xxx 指定错误日志文件的路径 nginx/logs/error.log
--http-log-path=xxx 指定访问日志文件的路径 nginx/logs/access.log
--pid-path=xxx 指定主进程 ID 文件(pid file)的路径,用于管理 nginx 进程 nginx/logs/nginx.pid
--modules-path=xxx 指定动态模块文件的存放目录 nginx/modules
--lock-path=xxx 指定运行期间用于进程同步的锁文件的路径 nginx/logs/nginx.lock
编译配置选项 含义及用途
--with-cc=xxx 指定用于编译 nginx 的 C 编译器路径,如果不指定,则默认使用系统环境中的 cc 或 gcc
--with-cpp=xxx 指定 C 预处理器路径
--with-cc-opt=[tag] 为 nginx 的 C 编译器添加额外的编译选项,常用于添加系统库的头文件路径或设置优化等级
--with-ld-opt=[tag] 为 nginx 的链接器添加额外的链接选项,常用于添加系统库的路径或 -Wl、-rpath 来指定运行时库路径
--with-cpu-opt=cpu 针对特定 CPU 架构进行优化,例如 amd64 或 i386,以生成更高效的代码
--with-debug 启用调试模式,在编译时包含调试符号,并启用额外的运行时调试日志和内存检查,但会稍微增加程序体积和运行时开销

一般无需自己指定,除非需要强自定义编译 nginx 来适用于特定场景

依赖配置选项 含义及用途
--without-pcre 明确指示不编译 pcre 模块,如果你不需要在配置中使用正则表达式(如 location ~ 或 rewrite),可以使用此选项
--with-pcre=xxx 启用 pcre 支持,并指定 pcre 源码的目录路径,当你需要使用特定版本或非系统默认安装的 pcre 时使用
--with-pcre-jit 启用 pcre 库的 JIT 编译功能,这可以显著提高正则表达式的匹配速度和性能,通常建议启用
--with-zlib=xxx 启用 gzip 压缩模块,并指定 zlib 源码的目录路径。用于编译时静态链接特定版本的 zlib
--with-zlib-opt=[tag] 编译 zlib 库时,传递额外的编译参数
--with-libatomic 强制在编译时使用 libatomic 库来实现原子操作,通常只有在 nginx 无法检测到硬件或编译器提供的原生原子操作指令时才需要
--with-openssl=xxx 启用 SSL/TLS 模块,并指定 openssl 源码的目录路径。用于编译时静态链接特定版本的 openssl
--with-openssl-opt=[tag] 为 nginx 编译 openssl 库时,传递 额外的编译参数(如用于排除某些不需要的协议或算法)

如果 nginx 的 configure 脚本没有明确禁止使用某个依赖项(如没有使用 --without-pcre),那么对于那些被视为核心或基础功能的依赖项,它默认会尝试在系统的标准路径下(如 /usr/lib, /usr/include 等)自动查找可用的库文件和头文件。所以上述的选项没有必要可不指定。

内置模块配置选项(部分) 含义与用途
--with-http_ssl_module 启用 SSL 模块,用于 HTTPS 协议
--with-http_v2_module 启用 HTTP/2 模块
--with-stream 启用四层 TCP 或 UDP 代理模块
--without-http_upstream_keepalive_module 禁用 HTTP Keepalive 模块
--without-http_rewrite_module 禁用 rewrite 模块
--add-module=xxx 静态编译第三方模块,用于将位于指定目录下的第三方模块源码一并编译进去,成为 nginx 可执行文件的一部分
--add-dynamic-module=xxx 动态编译第三方模块,用于将位于指定目录下的第三方模块编译成一个独立的动态链接库文件(.so 文件),而不是编译进主程序
--with-compat 启用动态模块兼容性模式,当你使用 --add-dynamic-module 选项时,如果同时指定 --with-compat,nginx 会尝试以一种更兼容的方式编译动态模块
  1. --with-*_module 选项:编译时默认不包含某些模块,可使用此系列命令将指定模块加入编译
  2. --without-*_module 选项:编译时默认包含了某些模块,可使用此命令将指定模块不加入编译
  3. --add-module=xxx 选项编译的三方模块,由软件自动加载,灵活性差,不支持热插拔,但是执行效率更高
  4. --add-dynamic-module=xxx 选项编译的三方模块,运行时需通过 load_module 指令加载,灵活性很高,可通过指令卸载更换,在 nginx 1.9.11 版本及其之后的版本中推荐使用
  5. --with-compat 选项:这个选项的主要目的是允许你编译出的动态模块能够被加载到主版本号相同、次版本号或修订版可能不同的 nginx 可执行文件中。如果你想在不重新编译模块的情况下升级 nginx 的小版本,建议使用此选项

随便写一个简单的配置命令,然后开始生成 makefile 文件并编译:

bash 复制代码
./configure --prefix=/etc/nginx \
    --sbin-path=/usr/sbin/nginx \
    --modules-path=/usr/lib64/nginx/modules \
    --with-compat \
    --with-file-aio \					# 启用异步文件 I/O,提高文件操作性能
    --with-threads \					# 启用线程池,优化慢速 I/O 操作(如磁盘读写)
    --with-pcre-jit \
    --with-http_ssl_module \
    --with-http_v2_module \
    --with-http_v3_module \				
    --with-http_realip_module \			# 启用 Real IP 模块,用于在反向代理后获取客户端真实 ip
    --with-http_stub_status_module \	# 启用 Stub Status 模块,提供基本的 nginx 状态监控页面
    --with-cc-opt='-O2 -march=native'	# 为 C 编译器添加优化选项。'-O2' 是优化等级,'-march=native' 让编译器针对当前 CPU 架构进行最佳优化

make -j 4 && make install				# 编译安装

出现如下语句表示编译文件生成成功:

nginx makefile文件生成成功

执行命令开始编译,等待编译完成:


nginx 编译成功

nginx 命令 含义
nginx 启动 nginx
nginx -s stop 快速关闭 nginx 服务(不等待工作进程处理完当前请求)
nginx -s quit 平滑停止 nginx 服务(等待工作进程处理完当前请求后退出)
nginx -s reload 重新加载配置文件,启动新的工作进程使用新配置,并平滑关闭旧的工作进程
nginx -s reopen 重新打开日志文件,常用于日志切割
nginx -V 显示 nginx 的版本、编译器版本和编译时的配置参数
nginx -t 测试配置文件的语法正确性,并尝试打开配置中引用的文件
nginx -c xxx 使用指定的配置文件,而不是默认的配置文件
nginx -g "xxx" 设置全局配置指令,这会覆盖配置文件中的同名指令

执行命令,运行 nginx 服务:

nginx 成功运行

包管理器安装

通过包管理器安装 nginx 是最简单、最快捷的方式,它会自动处理依赖,并集成到操作系统的服务管理系统(如 systemd)

如何选择:

  • 如果你是初学者或只需要一个基础稳定的 nginx 服务,推荐使用包管理工具安装,因为它最简单、最稳定,并且更容易与系统更新集成;
  • 如果你是高级用户,需要启用或禁用特定的模块(如需要一个官方包里没有的第三方模块),或者需要针对你的硬件进行性能进行优化,则推荐使用源码编译安装。

对于 Debian 系发行版:

bash 复制代码
sudo apt install nginx

对于 RedHat 系发行版:

bash 复制代码
# 某些旧版本或精简版的系统中,nginx 不在默认的软件仓库中,你可能需要先安装 epel 仓库
sudo yum install epel-release -y			# 对于 CentOS/RHEL 7 或更早版本使用 yum
sudo dnf install epel-release -y			# 对于 CentOS/RHEL 8 及以上或 Fedora 使用 dnf

# 安装 nginx
sudo dnf install nginx -y

启动 nginx:

bash 复制代码
sudo systemctl start nginx			# 启动 nginx 服务
sudo systemctl enable nginx 		# 设置为开机自启

可选项,可以优先更新系统软件后,再安装系统所支持的最新版 nginx:

bash 复制代码
sudo apt update			# Debian 系更新系统软件
sudo dnf update			# RedHat 系更新系统软件

Docker & Podman & K8s 安装 Nginx

在 Docker 或 Podman 中安装 nginx 非常简单,因为你只需要拉取官方的 nginx 镜像并运行它即可。在 k8s(Kubernetes)中安装稍显复杂,需要你非常熟悉 k8s。

拉取镜像:

bash 复制代码
# 针对没有加入集群化的 docker
docker pull nginx:latest			# 拉取最新的 nginx 镜像
docker pull nginx:stable			# 拉取最新的稳定版 nginx 镜像(推荐)

# 针对没有加入集群化 podman
podman pull nginx:stable

# 针对 k8s
kubectl create deployment myNginxs --image=nginx:stable --replicas=2		# 创建一个名为 myNginxs 的部署,使用官方 nginx 镜像,并运行 2 个副本
kubectl expose deployment myNginx \		# 创建 Service 抽象层
--name=nginx-nodeport-service \				
--port=8080 \								# 指定其他服务通过服务层访问 nginx 的入口为 8080
--target-port=80 \							# 指定服务层进入 nginx 的端口为 80
--type=NodePort								# 使用 NodePort 模式对外暴露服务

运行镜像:

bash 复制代码
# 针对 docker
docker run -d --name myNginx -p 8080:80 \
-v /opt/nginx/html:/usr/share/nginx/html:ro \			# 推荐将数据卷、配置文件等映射到宿主机上,方便后期运维管理
-v /opt/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro \
nginx:stable

# 针对 podman
podman run -d --name myNginx -p 8080:80 \
-v /opt/nginx/html:/usr/share/nginx/html:ro \
-v /opt/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro \
nginx:stable

# 针对 k8s
# 上述的 k8s 命令已经运行并对外暴露了服务,这里只需访问即可
kubectl get nodes -o wide			# 获取 k8s 集群中任一节点的 ip 地址
kubectl get service nginx-nodeport-service			# 获取 NodePort 服务所暴露的端口
# 上述命令获取信息后,通过 http://<任一节点 ip 地址>:<NodePort端口> 来访问 web 服务

注意:k8s 推荐使用 ymal 文件进行声明式操作,声明式操作支持持久化配置、滚动升级、增量更新、自动化等更多复杂配置,而上述的命令式操作只适用于简单场景。
当前容器编排市场中 k8s 是绝对主导,其他工具(如 Docker Swarm、Apache Mesos等)作为细分或小众补充的格局,其用户体量实在不及 k8s,而且它们应用场景也很特殊,所以这里就不做介绍了。

三、入门配置

配置文件结构

Nginx 的默认配置文件为 /usr/local/nginx/conf/nginx.conf,如果是通过包管理器安装的,那么配置文件为 /etc/nginx/nginx.conf。安装完成后,nginx 会提供一个 nginx.conf.default 文件,它可用于恢复初始配置。

打开 nginx.conf 文件,可以看到如下的文件解构,它们分别用 {} 包围:

  • 全局配置:没有 {} 包围,是最外层的配置项目,一般用于配置全局指令、用户组、进程 pid 路径、日志路径等;
  • events 块:此项中可配置服务驱动模型、worker最大连接数等;
  • http 块:此项中配置 HTTP 的处理行为,其中允许包含多个 server 块,可以配置绝大多数功能;
  • server 块:此项中配置 web 服务的相关参数,如监听端口、域名等;
  • location 块:此项中配置请求资源的路径和资源的处理行为。

配置文件组成

  • 指令:由名称和参数组成的,以分号(;)结尾;
  • 变量:nginx 的各个模块几乎都有很多变量,使用变量可以极大的提高灵活性,变量的使用方式是 $变量名
    • 内置变量:在 ngx_http_core_module 模块中存放了许多的内置变量,如获取请求参数的 arg_name、获取请求头中的 cookie 的 http_cookie 等等;
    • 自定义变量:可以在 server、http、events、location 中声明,声明方式为 set $名称 值。(不可以在顶层块中声明变量,这么做是无效的)

默认 nginx.conf 解析

顶级块配置信息解释:

复制代码
#user  nobody;							# worker 进程运行时所使用的用户和用户组
worker_processes  1;					# 启动 worker 进程的数量

#error_log  logs/error.log;				# 错误日志文件的路径和最低记录级别
#error_log  logs/error.log  notice;		# 通知级别的错误日志
#error_log  logs/error.log  info;		# 信息级别的错误日志,常用于调试

#pid        logs/nginx.pid;				# 主进程的 pid 文件路径

events 块配置信息解释:

复制代码
events {
    worker_connections  1024;			# 每个 worker 可以同时打开的最大连接数,一个完整的请求需要两个连接,实际并发数为此的一半
}

http 块配置信息解释:

复制代码
http {
    include       mime.types;			# include 指令引入外部文件,其定义了文件扩展名与 MIME 类型
    default_type  application/octet-stream;		# 当无法根据文件扩展名找到匹配的 MIME 类型时,所使用的默认 MIME 类型

	# 定义一个访问日志格式,并将其命名为 main
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;		# 启用访问日志,并指定日志文件的路径,再指定其格式为 main

    sendfile        on;		# 启用零拷贝文件传输,允许 nginx 直接在内核空间中将数据从磁盘文件句柄传输到网络套接字,提高静态文件服务的性能
    #tcp_nopush     on;		# 结合 sendfile 优化 TCP 传输,nginx 将尝试在一个 TCP 包中发送 HTTP 响应头和文件的开头部分,或者等待缓冲区满后再发送,有助于减少网络传输中的数据包数量,提高网络效率

    #keepalive_timeout  0;		# 禁用连接保持,所有连接在响应发送后立即关闭(设置为非 0 表示开启)
    keepalive_timeout  65;		# keep-alive 连接超时时间,允许客户端在指定的秒数内使用同一个 TCP 连接发送多个请求

    #gzip  on;			# 启用 gzip 压缩,可以显著减少传输的数据量,加快加载速度
	.....
	}

server 和 location 块配置信息解释:

复制代码
server {
        listen       80;			# 监听 80 端口
        server_name  localhost;		# 定义虚拟主机的需要响应的域名,localhost 表示响应所有没匹配到的域名,或响应直接通过 ip 的访问请求
        #charset koi8-r;			# 设置响应头中的字符集
        #access_log  logs/host.access.log  main;	# 设置这个特定虚拟主机的的访问日志,格式为 main

        location / {						# 设置 / 表示匹配所有传入请求,作为保底手段
            root   html;					# 定义这个 location 块的文档根目录,nginx 会在其安装目录下的 html 文件夹中查找请求的文件
            index  index.html index.htm;	# 定义访问此路径的首页文件
        }

        #error_page  404              /404.html;		# 指定此虚拟主机的 404 错误页面
        error_page   500 502 503 504  /50x.html;		# 指定此虚拟主机的 50x 错误页面
        
        location = /50x.html {							# 专门针对 50x 错误的请求,= 表示精准匹配 50x 错误需要查找的文件夹
            root   html;
        }

        #location ~ \.php$ {					# 代理 php,此 location 块匹配所有以 .php 结尾的请求
        #    proxy_pass   http://127.0.0.1;			# 将此请求转发到 localhost 主机上指定的另一个 web 服务器处理
        #}

        #location ~ \.php$ {					# 传递 php 到 fastcgi,将所有 .php 请求转发给 PHP-FPM 处理,这是 nginx 与 php 结合的推荐做法
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;			# 指定 fastcgi 服务器和端口
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;			# 设置 nginx 端和 fastcgi 通信的具体参数
        #    include        fastcgi_params;
        #}

        #location ~ /\.ht {				# 匹配所有以 .ht 开头的文件
        #    deny  all;					# 此指令拒绝对此文件的任何访问,提高安全性
        #}
    }

    #server {
    #    listen       8000;
    #    listen       somename:8080;				# 监听特定 ip 的特定端口
    #    server_name  somename  alias  another.alias;				# 处理所有指向 sonename、alias、another.alias 的请求

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

    #server {
    #    listen       443 ssl;					# 监听 443 端口,同时启用 SSL/TLS 来处理 https 请求
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;			# 指定 ssl 证书的路径,该文件包含服务器的公钥和身份信息
    #    ssl_certificate_key  cert.key;			# 指定 ssl 证书对应的私钥路径,此私钥必须严格保密,用于解密客户端发送的加密数据

    #    ssl_session_cache    shared:SSL:1m;	# 启用 ssl 会话缓存,创建一个名为 SSL、大小为 1m 的共享内存来存储会话参数,这允许客户端在短时间内重连而无需再次进行完整的 TLS 握手
    #    ssl_session_timeout  5m;				# 设置 ssl 会话参数在缓存中保持有效的时间限制,此处为 5 分钟
	
    #    ssl_ciphers  HIGH:!aNULL:!MD5;			# 设置在 TLS 握手中接受或优先使用的加密算法列表
    #    ssl_prefer_server_ciphers  on;			# 设置为 on 时,nginx 将优先使用自定义的加密算法列表,而不是听从客户端建议的算法

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

nginx 中的一些常用变量及其含义:

变量名 含义 用处
remote_addr / remote_port 客户端的 ip 地址 / 端口 限制访问、安全规则
$remote_user 经过 HTTP Basic Authentication 认证的用户名 权限控制
$request_method 客户端的请求方法( GET, POST, PUT...) 权限判断
$uri 当前请求的 url,不带参数 rewrite 重写、location 匹配
$request_uri 包含请求参数的完整 url 规则重写
$host 请求头中的 Host 字段(如果缺失,则使用 server_name) 反向代理、虚拟主机判断
query_string / args 请求 url 中的参数部分(在 ? 之后的部分) 重写、参数传递给后端
$http_user_agent 客户端的 user-agent 字段(浏览器信息) 移动端判断
$http_referer 客户端的 referer 字段(请求来源 URL) 防盗链
$status 发送给客户端的响应状态码(200, 404, 500...) 访问日志
$content_type 响应头中的 content-type 字段 调试
$sent_http_xxx 响应头中名为 xxx 的字段值(如 $sent_http_content_type) 访问日志
server_addr / server_port 接收请求的服务器 ip 地址 / 端口 访问日志、调试
$server_name 接收请求的虚拟主机名(server_name 指令值) 调试
$document_root 当前请求的 root 或 alias 指令设置的值 fastcgi_param SCRIPT_FILENAME
$time_local 服务器本地时间 访问日志
$http_x_forwarded_for 客户端 ip 地址的列表,当请求经过多个代理时生成 获取真实客户端 ip
$scheme HTTP 协议方案 HTTPS 重定向
$request_time 请求处理的总耗时(以秒为单位,精确到毫秒) 性能日志

四、NGINX 升级

源码编译升级

Nginx 的平滑升级是其不停机维护的核心能力之一,它允许你在不中断现有服务的情况下,逐步替换 nginx 的二进制文件并切换到新版本。

第一步、下载并编译新版的 nginx 源码:

  • 在新版 nginx 源码目录下,使用与旧版本 nginx 相同的 ./configure 参数进行配置和编译;

    警告:必须使用与旧版本相同的配置参数,否则可能导致配置文件路径、模块缺失等问题。

  • 此时只执行 make不要执行 make install,因为 make install 会直接覆盖旧版本,导致现有服务中断;

第二步、替换旧文件:

  • 将 make 后生成的二进制文件替换掉旧的二进制文件,只需复制新编译的二进制文件到目标路径即可 推荐备份旧的二进制文件,防止出现意料之外的情况

第三步、启动新的 master 进程:

  • 向旧版本的 master 进程发送 USR2 信号

    bash 复制代码
    kill -USR2 $(cat nginx.pid)
  • 发送 USR2 信号后,旧的 master 进程会重命名其 pid 文件,然后启动一个新版本的 master 进程,新进程开始加载配置并启动新的 worker 进程,最后新旧版的 worker 进程同时运行,共同处理请求。

第四步、逐步切换流量:

  • 向旧的 master 进程发送 QUIT 信号

    bash 复制代码
    sudo kill -QUIT xxxx
  • 发送 QUIT 信号后,旧 worker 进程将不再接受新连接,它将等待处理完现有连接后优雅退出,一旦所有旧 worker 进程退出,旧的 master 进程也会退出。到达这一步,nginx 顺利平滑升级完成。

包管理器升级

包管理器平滑升级就简单多了,但核心原理依然是利用 nginx 的 master 进程信号控制,以实现零停机时间。

通过 apt 或 dnf 升级 nginx 二进制包,然后通过 sudo systemctl restart nginx 即可完成平滑升级。

许多发行版的 nginx 服务脚本已经被配置成在 restart 时执行必要的平滑切换步骤,或者直接使用新 master 进程启动。但为了保证零停机,使用 USR2/QUIT 信号是最稳妥和透明的方法。

Docker & Podman & K8s 升级 Nginx

  1. 针对没有加入集群化的 docker 和 podman:
  • 启动新的 nginx 容器,但必须映射到不同的宿主机端口;

  • 如果你在 nginx 容器前使用了一个负载均衡器,则将其配置从旧端口切换到新端口;

  • 通知旧容器优雅退出,停止旧容器时,发送 SIGQUIT 信号(而不是默认的 SIGTERM 或 SIGKILL);

  • 移除旧容器并释放旧端口即可。

    在 docker/podman 环境中执行 nginx 的平滑升级时,新旧容器的配置项应该尽量保持一致,主要变动应该仅限于镜像版本和端口映射。
    不能简单地 docker restart 或 podman restart,这么做虽然 nginx 内部可以实现优雅关闭,但在重启那一瞬间,宿主机的端口映射会断开,导致短时间内的服务中断。

  1. 针对 k8s:

    bash 复制代码
    # 直接将 nginx 从旧版升级到 1.28 版本
    kubectl set image deployment/myNginxs nginx-container=nginx:1.28

    k8s 是实现真正全自动平滑升级的最佳平台,它通过 deployment 资源的滚动更新策略,在集群级别自动管理应用的零停机升级。在整个过程中,k8s 会逐步优雅的替换掉旧的 pod,而 Service 的 ClusterIP 和端口却始终保持不变,并且 Service 后端总是有健康的 Pods 响应请求,从而实现了真正的零停机升级。

五、Angie 安装、配置、升级

angie 的安装、配置和升级在很多方面与 nginx 高度相似,但由于 angie 是 nginx 的一个 分支,它有自己的特定名称、二进制文件路径和额外的功能/指令。

相似之处:

  • 配置语法几乎完全一样,nginx 配置文件(nginx.conf、server 块、location 块等)可以直接用于 angie,所有标准的 nginx 指令(如 listen、proxy_pass、root、set 等)在 angie 中都有效;
  • 源码编译所需的依赖库(如 pcre, zlib, openssl 等)与 nginx 相同;
  • 用于测试配置、启动、停止和重新加载配置的信号控制(如 kill -HUP 或 angie -s reload)与 nginx 相同;
  • 许多标准的 nginx 模块(如 http_ssl_module、http_gzip_module 等)在 angie 中也可用;
  • 平滑升级的原理和具体操作完全一样。

不同之处:

  • angie 引入了一些 nginx 没有的新功能和新的模块指令,例如改进的缓存管理、更高级的负载均衡算法或新的 metrics 导出功能,如果你需要使用这些新功能,配置指令就会不同。
相关推荐
乘云数字DATABUFF4 天前
5分钟部署开源APM Databuff:OpenTelemetry全链路追踪入门实战
运维·后端
荣--6 天前
一键部署不是为了省时间 —— 它是把"买来的 PaaS"变成"自己的平台"的拐点
运维·zabbix·工程化·一键部署·平台化·边界设计
江华森6 天前
动手实战学 Docker — 从零到集群编排完全指南
运维
Avan_菜菜7 天前
FRP 内网穿透完整实战:从 HTTP 映射到 HTTPS 自签代理
运维·nginx·https
SelectDB8 天前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
XIAOHEZIcode9 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户03284722207010 天前
如何搭建本地yum源(上)
运维
ping某11 天前
为什么 Nginx 明明监听了 80,转发后端时却用了 4xxxx 端口?
后端·nginx
大树8813 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠13 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql