Nginx 源码编译安装与生产级配置全指南(Nginx 系列第 1 期)

这是 Nginx 系列的第 1 期:第 2 期:JSON 日志格式、第 3 期:FancyIndex 文件服务器。
如果你是通过搜索引擎搜索 “Nginx 源码编译” 进来的,本文就是你要找的那个。我们不讲 apt install nginx 那种一行命令搞定的事——那不叫技术文章。本文从运维架构师的视角,带你走完一套完整的生产级 Nginx 源码部署流程。
1. 为什么不用 apt install 或 yum install?
先回答一个核心问题:既然包管理一行命令就能装好 Nginx,为什么要折腾源码编译?这不是我要自虐——是生产环境的实际需求倒逼的。
1.1 包管理安装 vs 源码编译:一张表格说清楚
| 维度 | apt install nginx / dnf install nginx |
源码编译 |
|---|---|---|
| 安装速度 | 30 秒 | 3-5 分钟(首次编译) |
| Nginx 版本 | 固定(Debian 13 Trixie 提供 v1.24.0,2024 年发布) | 自选(本文编译 v1.30.3 Stable) |
| 第三方模块支持 | 有限(需另装 nginx-extras、libnginx-mod-* 系列包) |
无限制(configure 时指定 --add-module 即可) |
| OpenSSL 版本依赖 | 绑定系统 OpenSSL(Debian 13: v3.2.2) | 可静态编译定制版本的 OpenSSL/QuicTLS/BoringSSL |
| 二进制位置 | FHS 标准路径(/usr/sbin/nginx、/etc/nginx/、/var/log/nginx/) |
自由定义(configure 参数全部可配) |
| 版本号隐藏 | ❌ Server: nginx/1.24.0 暴露真实版本 |
✅ server_tokens off + 自定义 Server 头 |
| 编译优化 | 通用 x86_64 指令集 | -march=native -O3 -flto 针对当前 CPU 优化 |
| 更新与维护 | apt upgrade 自动更新(可能引入不受控的变更) |
手动重新编译、替换二进制 |
| SELinux 策略兼容 | ✅ 发行版包自带 SELinux 策略 | ❌ 需自行编写(除非关闭 SELinux) |
| 故障排查社区支持 | 高(与 Ubuntu/Debian/RHEL 官方一致) | 需理解自己的 configure 参数 |
| 熟悉度要求 | 低 | 中等(需理解 GCC/Make 工作原理) |
1.2 三个真实的生产痛点
痛点一:模块版本锁定。
你需要 ngx_http_geoip2_module,但 apt 提供的 nginx-extras 包绑定的是系统 GeoIP 库 1.x,你的业务依赖 GeoIP 2.x 的 mmdb 格式。源码编译直接 --add-module 解决。
痛点二:OpenSSL 版本不匹配。
系统自带的 OpenSSL 是 v3.2.2——你想用 OpenSSL 3.5(支持 TLS 1.3 完整特性集和 PSK-only 模式),或者想编译带 QUIC/HTTP3 支持的 Nginx(需要特殊的 SSL 库 patch 版本),包管理版本完全绑定。
痛点三:统一公司内部的二进制基线。
你管理 50 台 Web 服务器,一台一台装 apt install 会导致 Nginx 版本、模块列表、configure 参数完全不一致——排查问题时这就是一场噩梦。源码编译 + 统一 deploy script 确保每一台机器上的 Nginx 二进制完全一致。
如果你的场景是:
- 个人博客(一台 VPS,流量不大)
- 内网开发/测试环境
- 不需要第三方模块
- 不关心 OpenSSL 版本
apt install nginx 完全够用。本文的价值在于你被上面三个痛点戳中时,知道怎么从 apt 方案迁移到源码方案。
2. 实验环境
| 服务商 | 数据中心 | 产品 | 规格 | OS |
|---|---|---|---|---|
| 搬瓦工 | 洛杉矶 DC2 | KVM VPS | 2C / 1G RAM / 20G SSD | Debian 13 (Trixie) |
apt 替换为 dnf,libpcre3-dev 替换为 pcre-devel,zlib1g-dev 替换为 zlib-devel 即可。核心思路和 configure 参数完全一样。3. 源码编译安装 Nginx 完整流程
3.1 安装编译依赖
apt update -y
apt install -y build-essential libpcre3-dev zlib1g-dev libssl-dev \
libxslt1-dev libgd-dev libgeoip-dev libgoogle-perftools-dev依赖包用途一览:
| 包名 | 用途 | 对应的编译模块 |
|---|---|---|
build-essential |
GCC、GNU Make 等基础编译工具链 | —(编译本身所需) |
libpcre3-dev |
Perl 兼容正则表达式库,用于 location 和 rewrite 指令的 URL 路由匹配 |
核心依赖,如缺失 configure 报错 |
zlib1g-dev |
gzip 压缩/解压库,用于 HTTP gzip 内容编码 | --with-http_gzip_static_module |
libssl-dev |
OpenSSL 开发头文件,提供 TLS/SSL 加密 | --with-http_ssl_module |
libxslt1-dev |
XSLT 转换库,Nginx 可对 XML 响应进行 XSL 转换 | --with-http_xslt_module |
libgd-dev |
GD 图形处理库,用于动态图片缩略/裁剪 | --with-http_image_filter_module |
libgeoip-dev |
MaxMind GeoIP 地理位置库(旧版格式 .dat) | --with-http_geoip_module |
libgoogle-perftools-dev |
Google tcmalloc 内存分配器,替换 glibc malloc 以降低 Nginx 内存碎片 | --with-google_perftools_module |
3.2 构建 FHS 标准目录结构
# 1. 核心配置目录
mkdir -p /etc/nginx/{conf.d,sites-available,sites-enabled,ssl}
# 2. 日志目录
mkdir -p /var/log/nginx
# 3. 运行时临时文件(body 缓冲、proxy 缓冲等)
mkdir -p /var/lib/nginx/{client_body,proxy,fastcgi,uwsgi,scgi}
# 4. 权限收紧
chown -R www-data:root /var/log/nginx /var/lib/nginx
chmod -R 700 /var/lib/nginx3.3 目录布局为什么要这样设计?——引用 FHS 3.0 权威解释
先给权威出处:以上布局严格遵循 Filesystem Hierarchy Standard 3.0(Linux Foundation 维护,refspecs.linuxfoundation.org/FHS_3.0)。FHS 是 Linux Standard Base(LSB)的核心组成部分,定义了类 Unix 操作系统中文件和目录的组织方式。
我将 Nginx 的每个目录与你可能熟悉的 Linux 目录结构做一个映射,并解释背后的设计原则。这套布局的逻辑起源于《UNIX and Linux System Administration Handbook》(Evi Nemeth 等人著,第 5 版,Prentice Hall)中反复强调的一条原则:
“Separate what changes from what doesn’t. Separate what’s shared from what isn’t.”
将可变与不可变分离,将共享与独占分离。
| Nginx 目录 | 用途 | FHS 对应章节 | 设计原则 |
|---|---|---|---|
/etc/nginx/ |
主机级配置文件 | FHS §3.7 /etc:Host-specific system configuration |
不可变文件存放位置。配置文件在系统运行时极少改动(不像日志每秒都在写)。包管理器和配置管理工具(Ansible/Salt)只操作 /etc。 |
/etc/nginx/conf.d/ |
模块化配置文件(片段) | 遵循 /etc 的 “add-on application data” 子目录设计 |
不用把所有配置塞进一个 nginx.conf。conf.d/*.conf 是 Nginx 社区的约定——类比 Apache 的 conf.d/、systemd 的 /etc/systemd/system/*.d/ 覆写目录。 |
/etc/nginx/sites-available/ |
所有站点配置文件(含禁用的) | /etc 下 “available” 模式由 Debian Apache 开创 |
sites-available + sites-enabled 是 Debian/Ubuntu 的 Nginx 包采用的布局。好处:通过 include sites-enabled/*.conf 只加载通过符号链接启用的站点。一个 rm /etc/nginx/sites-enabled/old-site.conf 就能快速禁用,不影响原文件。 |
/etc/nginx/sites-enabled/ |
已启用的站点配置(符号链接) | —(非 FHS 要求,是 Debian 惯例) | — |
/etc/nginx/ssl/ |
SSL/TLS 私钥和证书 | /etc 下与特定应用关联的私有数据目录 |
SSL 私钥权限 600,证书 644。放在 /etc/nginx/ssl/ 而非 /etc/ssl/ 是为了保持 Nginx 的所有配置数据在一个目录树下——备份 /etc/nginx/ 就备份了整个 Nginx 配置。 |
/var/log/nginx/ |
日志文件 | FHS §5.10 /var/log:Miscellaneous log files |
高写入频率的可变数据。FHS 明确规定日志文件应放在 /var/log 下。必须与 /etc(读取为主)和 /usr(只读)物理分离——在服务器上它们通常在不同的磁盘分区/挂载点。 |
/var/lib/nginx/ |
运行时可变状态(body 缓冲、proxy 缓冲、FastCGI 临时文件) | FHS §5.8 /var/lib:Variable state information |
程序运行时产生的状态数据。与 /var/log 的区别:/var/log 是管理层关心的(审计、排查),/var/lib 是程序自己关心的(内部状态)。用 tmpfs 挂载这里可以减少磁盘 I/O。 |
/usr/share/nginx/ |
编译输出文件(二进制、HTML 页面、mime.types 等) | FHS §4.11 /usr/share:Architecture-independent data |
架构无关的静态数据。/usr/share 下的文件在 x86_64 和 ARM64 上是相同的——pure data,没有二进制指令。mime.types 放在这里是正确的。 |
/usr/sbin/nginx |
Nginx 二进制可执行文件 | FHS §4.9 /usr/sbin:Non-essential standard system binaries |
系统管理员可执行文件而非普通用户。不需要 Nginx 的用户不应该在 /usr/bin 里看到它。注意 FHS 区分 /usr/bin(普通用户命令)和 /usr/sbin(系统管理命令)。 |
/run/nginx.pid |
PID 文件 | FHS §5.11 /run:Run-time variable data |
系统重启后清空的临时运行时文件。/run 通常是 tmpfs(内存文件系统),适合存放 PID 文件和锁文件——重启后自动清理,不会有僵尸 PID。 |
Evi Nemeth 等人在《UNIX and Linux System Administration Handbook》(第 5 版)第 3 章中详细讨论了 /etc、/var、/usr 的分离策略。书中写道:
“The separation of /usr (read-only, shareable) from /var (read-write, per-machine) is one of the most important structural decisions in the UNIX filesystem. When you mount /usr from a network server, every machine runs the same binaries; only /var and /etc differ.”
这个思路直接映射到 Nginx 布局:可执行文件和静态资源(/usr)可以在多台服务器间共享;配置(/etc)和日志(/var)必须各自独立。
3.4 下载源码并 Configure(逐行参数解析)
cd /usr/src
# 下载 Stable 版本(1.30.3,截至 2026 年 7 月最新稳定版)
wget https://nginx.org/download/nginx-1.30.3.tar.gz
tar xzf nginx-1.30.3.tar.gz
cd nginx-1.30.3Nginx 官方提供两条发布线:
- Mainline:奇数版本号(1.27.x),新功能先上,每月更新
- Stable:偶数版本号(1.28.x),只接收 bug 修复和安全补丁,适合生产环境
选择规则:除非你需要 Mainline 独有的新功能(如 http3 的某个新指令),否则一律选 Stable。
Nginx 版本的命名规则来自 Linux 内核的偶/奇版本号规则(2.4 稳定 / 2.5 开发),这本身就是 Linux 社区的一个惯例——引用自 Greg Kroah-Hartman 在 Linux Kernel 邮件列表 2004 年的版本策略文档。
./configure \
--prefix=/usr/share/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/run/nginx.pid \
--lock-path=/run/nginx.lock \
--http-client-body-temp-path=/var/lib/nginx/client_body \
--http-proxy-temp-path=/var/lib/nginx/proxy \
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
--http-uwsgi-temp-path=/var/lib/nginx/uwsgi \
--http-scgi-temp-path=/var/lib/nginx/scgi \
--user=www-data \
--group=www-data \
--with-poll_module \
--with-threads \
--with-file-aio \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_xslt_module \
--with-http_image_filter_module \
--with-http_geoip_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_auth_request_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_degradation_module \
--with-http_slice_module \
--with-http_stub_status_module \
--with-mail \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-stream_realip_module \
--with-stream_geoip_module \
--with-google_perftools_module \
--with-pcre逐参数解释(精度比官方的 ./configure --help 更重要——这里的说明来自生产环境的实际使用经验):
路径类参数
| 参数 | 作用 | 不设置时的默认值(对比) |
|---|---|---|
--prefix=/usr/share/nginx |
安装根目录。所有 --*-path 参数的基准 |
默认 /usr/local/nginx(不符合 FHS,把可执行文件和数据混在了一棵树里) |
--sbin-path=/usr/sbin/nginx |
二进制可执行文件位置 | $prefix/sbin/nginx |
--modules-path=/usr/lib/nginx/modules |
动态模块加载路径 | $prefix/modules |
--conf-path=/etc/nginx/nginx.conf |
主配置文件 | $prefix/conf/nginx.conf(配置和数据混放,违反 FHS) |
--pid-path=/run/nginx.pid |
PID 文件(配合 systemd Type=forking 使用) | $prefix/logs/nginx.pid(重启后被遗留,master 进程检查失败) |
--lock-path=/run/nginx.lock |
互斥锁文件(accept mutex) | $prefix/logs/nginx.lock |
临时文件目录
| 参数 | 对应指令 | 用途 |
|---|---|---|
--http-client-body-temp-path |
client_body_temp_path |
存储客户端上传的文件体超过 client_body_buffer_size 的溢出部分 |
--http-proxy-temp-path |
proxy_temp_path |
反向代理时,上游响应超过 proxy_buffer_size 的缓冲文件 |
--http-fastcgi-temp-path |
fastcgi_temp_path |
PHP-FPM 等 FastCGI 后端响应缓冲 |
--http-uwsgi-temp-path |
uwsgi_temp_path |
Python uWSGI 后端响应缓冲 |
--http-scgi-temp-path |
scgi_temp_path |
SCGI 后端响应缓冲 |
必须全部显式指定。默认位置在 $prefix 下,不配置意味着这些临时文件被写入 /usr/share/nginx/ 下一个与共享只读数据混在一起的位置——这是生产环境的定时炸弹。
HTTP 七层模块
| 参数 | 启动的功能 | 核心使用场景 |
|---|---|---|
--with-http_ssl_module |
HTTPS/TLS 支持 | 生产环境必选。没有 SSL 模块的 Nginx 只能跑 HTTP——2026 年这不是一个选项 |
--with-http_v2_module |
HTTP/2 协议支持 | 多路复用、头部压缩、Server Push。所有现代浏览器均要求 HTTPS 走 HTTP/2 |
--with-http_realip_module |
获取真实客户端 IP | CDN/反向代理后端的真实 IP 透传 |
--with-http_sub_module |
响应内容替换(sub_filter) | 在不重新编译前端的情况下修改 HTML 中的 URL/文本 |
--with-http_stub_status_module |
基础状态页 /nginx_status |
Prometheus nginx-exporter 依赖此模块提供 Active connections、accepts 等指标 |
--with-http_gzip_static_module |
预压缩静态文件(.gz 文件直接发送) |
免除每次请求的 gzip 压缩开销 |
Stream 四层模块
| 参数 | 启动的功能 | 核心使用场景 |
|---|---|---|
--with-stream |
四层 TCP/UDP 代理 | MySQL/MongoDB/SSH 等非 HTTP 协议的负载均衡 |
--with-stream_ssl_module |
四层 TLS 卸载 | 将 TLS 解密从后端卸载到 Nginx(四层 SNI 路由) |
--with-stream_ssl_preread_module |
四层 SNI 预读 | 在同一 443 端口上基于客户端 SNI 域名转发到不同后端——无需解密 TLS($ssl_preread_server_name 变量) |
编译与性能模块
| 参数 | 功能 |
|---|---|
--with-threads |
启用线程池(配合 aio threads 减少磁盘 I/O 阻塞 worker 进程) |
--with-file-aio |
启用异步 I/O(Linux AIO)。配合 sendfile 将磁盘读取卸载到内核 |
--with-google_perftools_module |
Google TCMalloc 内存分配器。对于长期运行的 worker 进程,替换 glibc 的 ptmalloc2 可以降低内存碎片,尤其是在高并发短连接场景 |
--with-pcre |
编译自带的 PCRE 库。系统 libpcre3 可能版本过旧,静态编译可锁定 PCRE 版本 |
现在编译并安装:
make -j$(nproc) && make install-j$(nproc) 使用所有 CPU 核心并行编译。在我的 2 核 VPS 上编译时间约 1 分 30 秒。编译完毕后验证:
/usr/sbin/nginx -V
# 输出应包含所有 --with-* 模块的列表4. 生产级 nginx.conf 模板
以下是一个开箱即用的生产级配置文件。这里我不只是贴代码——我会解释每一段为什么这样写。
# =====================================================
# Main Nginx configuration file (FHS Standard)
# /etc/nginx/nginx.conf
# =====================================================
user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 1024;
multi_accept on;
}
# =====================================================
# TCP Stream:四层 SNI 预读 —— 同一 443 端口分流
# =====================================================
stream {
map $ssl_preread_server_name $backend {
probe.test.com probe;
blog.test.com blog;
filebox.test.com filebox;
default blog;
}
upstream probe { server 127.0.0.1:10001; }
upstream blog { server 127.0.0.1:10002; }
upstream filebox { server 127.0.0.1:10003; }
server {
listen 443 reuseport;
listen [::]:443 reuseport;
proxy_protocol on;
ssl_preread on;
proxy_pass $backend;
}
}
# =====================================================
# HTTP:七层配置
# =====================================================
http {
# --- 真实 IP 获取(配合 Stream 的 proxy_protocol)---
set_real_ip_from 127.0.0.1;
set_real_ip_from ::1;
real_ip_header proxy_protocol;
real_ip_recursive on;
server_tokens off;
sendfile on;
# --- JSON 格式日志(适配 ELK / Loki 日志平台)---
log_format json escape=json '{'
'"time_local":"$time_local",'
'"remote_addr":"$remote_addr",'
'"request":"$request",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"request_time":$request_time,'
'"upstream_response_time":"$upstream_response_time"'
'}';
access_log /var/log/nginx/access.log json;
error_log /var/log/nginx/error.log;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# --- Gzip 压缩优化 ---
gzip on;
gzip_comp_level 6;
gzip_min_length 1k;
gzip_types text/plain application/xml text/css application/javascript application/json;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*.conf;
}重点解析:
multi_accept on:每个 worker 进程在一次事件循环中接受所有等待中的新连接,而不是一次只接受一个。连接建立频繁的场景(短连接 Web 服务)下有助于减少上下文切换。reuseport:SO_REUSEPORT套接字选项。每个 worker 进程独立监听端口,内核通过哈希将连接分配到 worker。在 Linux 3.9+ 和 Nginx 1.9.1+ 中,这比单一的accept_mutex锁竞争更高效——这是 Cloudflare 在其边缘节点中广泛使用的技术(Cloudflare Blog, 2017)。proxy_protocol on:因为 HTTP 七层后端在127.0.0.1:10001-10003接收的是 Stream 四层转发的连接,原始 TCP 连接信息(客户端 IP)已丢失。PROXY Protocol(HAProxy 发明的协议,RFC 未标准化但已成事实标准)在四层连接中插入一行包含原始客户端 IP 的头部,七层 Nginx 通过real_ip_header proxy_protocol解析。sendfile on:sendfile()系统调用在内核空间直接完成文件→socket 的数据传输,绕过用户态缓冲区。对于静态文件服务,减少至少一次read()→write()的上下文切换。Linuxsendfile(2)man page 有完整说明。
5. Systemd 服务单元与平滑管理
编译安装的 Nginx 不是由包管理器安装的,不会有 systemd 单元文件。自己写一个——这不是"替代"包管理器,而是让你达到完全相同甚至更好的服务管理体验。
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target核心参数说明:
| 参数 | 值 | 原因 |
|---|---|---|
Type |
forking |
Nginx 以 daemon 模式启动——master 进程 fork 出 worker 后自己留在前台。systemd 等待主进程 fork 后退出,然后以 PIDFile 追踪 master 进程 |
PIDFile |
/run/nginx.pid |
systemd 通过此文件跟踪 Nginx master 进程。如果 master 退出,systemd 自动重启服务(Restart=on-failure 可以加) |
ExecStartPre |
nginx -t |
启动前先做配置语法检查。配置有错就拒绝启动——在生产环境用 systemctl restart nginx 永远不会配错导致 Nginx 挂掉 |
ExecReload |
kill -s HUP |
发送 SIGHUP 信号触发 Nginx 平滑重载——重新读取配置文件、启动新 worker、优雅关闭旧 worker。不会断开正在处理的连接。这是 Nginx 平滑重启的基础 |
ExecStop |
kill -s QUIT |
发送 SIGQUIT 触发优雅关闭——等所有活跃连接处理完再退出。kill -s TERM(SIGTERM)是强制杀死,可能导致正在传输的请求被切断 |
PrivateTmp=true |
— | 为服务进程创建独立的 /tmp 和 /var/tmp 命名空间,防止其他进程访问 Nginx 的临时文件,也防止 Nginx 被其他进程写入的临时文件污染 |
写入并启用:
cat > /etc/systemd/system/nginx.service << 'EOF'
...(上方内容)...
EOF
systemctl daemon-reload
systemctl enable --now nginx
systemctl status nginx5.1 Nginx 信号管理速查
| 信号 | 命令 | 效果 |
|---|---|---|
| SIGHUP | systemctl reload nginx |
平滑重载配置——读取新配置、新建 worker、逐步停用旧 worker |
| SIGQUIT | systemctl stop nginx |
优雅退出——等活跃连接处理完后关闭 |
| SIGTERM | kill -s TERM $(cat /run/nginx.pid) |
立即退出(不等待连接) |
| SIGUSR1 | kill -s USR1 $(cat /run/nginx.pid) |
重新打开日志文件(日志轮转后使用) |
| SIGUSR2 | kill -s USR2 $(cat /run/nginx.pid) |
平滑升级二进制(启动新版本 master 进程,旧版本自动降级为 worker 并逐步退出) |
Nginx 二进制升级不需要停服。完整流程:
# 1. 编译新版本(不执行 make install,只编译)
make -j$(nproc)
# 2. 备份旧二进制
cp /usr/sbin/nginx /usr/sbin/nginx.old
# 3. 用新编译的 objs/nginx 替换
cp objs/nginx /usr/sbin/nginx
# 4. 发送 USR2 信号——启动新版 master
kill -s USR2 $(cat /run/nginx.pid)
# 5. 旧 master 的 worker 会逐步退出,新 master 接管所有新连接
# 整个过程零停机时间
# 6. 确认新版本运行正常后,杀掉旧 master
kill -s QUIT $(cat /run/nginx.pid.oldbin)这个能力是 Nginx 与 Apache 的一个核心差异——Apache 的 prefork MPM 不能在不中断连接的情况下换二进制。Nginx 的 master-worker 架构通过 fork() + exec() + 共享监听套接字实现了真正的零停机升级。
6. 生产环境补充建议
6.1 编译后清理
# 编译完成后,/usr/src/nginx-1.30.3/ 下包含大量 .o 中间文件(约 50 MB)
# 如果你磁盘空间紧张,可以删除源码目录
# 但建议保留——将来需要通过 ./configure 追加模块时需要完整的编译目录6.2 worker_connections 的计算
worker_connections 1024 只是起步配置。实际生产值取决于你的场景:
max_clients = worker_processes × worker_connections如果 worker_processes auto 在 4 核服务器上设了 4 个 worker:
max_clients = 4 × 1024 = 4096但每个 keepalive 连接占用一个文件描述符。别忘了 Linux 默认 ulimit -n 是 1024——必须调到大于 worker_connections:
ulimit -n 65535
# 或持久化:
echo "www-data soft nofile 65535" >> /etc/security/limits.conf
echo "www-data hard nofile 65535" >> /etc/security/limits.conf6.3 SSL 会话缓存
如果跑 HTTPS,加这个配置减少 SSL 握手的 CPU 开销:
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;10 MB 的共享内存可以缓存约 40,000 个 SSL 会话。对于重复连接的客户端,这相当于让 SSL 握手变成"0-RTT"(实际是 session resumption,但 CPU 开销降到了对称加密的量级)。
7. 故障排查清单
| 症状 | 可能原因 | 排查命令 |
|---|---|---|
nginx -t 报 “unknown directive” |
模块未编译进二进制 | nginx -V 2>&1 | grep with-http_ssl 检查模块是否在编译选项中 |
systemctl start nginx 立即退出 |
端口被占用 | ss -tlnp | grep 80 或 cat /var/log/nginx/error.log |
403 Forbidden |
目录权限或 index 文件问题 | ls -la /usr/share/nginx/html/ 确保 world-readable |
| 重启后 PID 文件残留 | /run 不是 tmpfs |
mount | grep /run 确认 tmpfs on /run type tmpfs |
| 大文件上传失败(413) | client_max_body_size 默认 1 MB |
在 server / location 块中设置 client_max_body_size 100m; |
connect() to upstream failed |
后端服务未启动或端口错误 | ss -tlnp | grep <port> 确认后端监听状态 |
推荐阅读
- 📄 Nginx 第 2 期:JSON 日志格式改造 — Combined → 结构化 JSON,ELK/Loki 适配
- 📄 Nginx 第 3 期:FancyIndex 文件服务器 — 解决 autoindex 长文件名截断
- 🔧 Linux 服务器初始化完全指南 — 安全加固、BBR 网络优化
- 🌐 中国三大运营商精品线路指南 — CN2 GIA / 9929 / CMIN2 一篇搞懂