🚀 Nginx 软件设计架构与详细教程

IT 技术 99 阅读 更新于 2026-09-25 17:39

从架构原理到生产实践的完整指南 — 涵盖高性能 Web 服务器、反向代理与负载均衡

📋 目录索引

一、Nginx 概述

1.1 什么是 Nginx?

Nginx 简介

Nginx(发音为 "engine-x")是一个开源的、高性能的 HTTP 和反向代理服务器,同时也提供了 IMAP/POP3/SMTP 邮件代理服务。它由俄罗斯程序员 Igor Sysoev 于 2002 年开始开发,2004 年正式发布,旨在解决 C10K 问题(同时处理 10,000 个并发连接)。

💡 核心特点:

Nginx 采用异步非阻塞的事件驱动架构,相比传统的 Apache 进程/线程模型,在高并发场景下具有显著的性能优势和更低的资源消耗。

主要功能

🌐 Web 服务器

高性能静态文件服务,支持 HTTP/2、HTTPS、gzip 压缩等

🔄 反向代理

将客户端请求转发到后端服务器,隐藏后端拓扑

⚖️ 负载均衡

支持多种负载均衡算法,分发流量到多个后端

📦 静态文件服务

高效的静态内容缓存与分发

🔐 SSL/TLS 终端

SSL 卸载、证书管理、HTTPS 加速

📊 缓存代理

反向代理缓存,减少后端压力

市场份额

根据 W3Techs 的统计数据,Nginx 在全球活跃网站中的使用率超过 30%,在流量最大的 1000 个网站中使用率超过 40%,是全球使用最广泛的 Web 服务器之一。

特性NginxApache
架构模型事件驱动(异步非阻塞)进程/线程(多进程模型)
并发连接数万级轻松处理数千级(受进程限制)
内存消耗极低(每连接数 KB)较高(每连接数 MB)
静态文件处理极快较快
动态内容处理需要配合 FastCGI/uWSGI内置模块支持
配置复杂度简洁清晰功能丰富但较复杂

1.2 Nginx 版本与许可

版本类型

  • Nginx OSS(开源版):采用 2-clause BSD 许可证,完全免费开源
  • Nginx Plus(商业版):F5 公司(2019 年收购 Nginx)提供的企业级版本,包含额外功能和技术支持
  • Nginx 版本命名规则:偶数版本号(如 1.24、1.26)为稳定版,奇数版本号(如 1.25、1.27)为开发版

版本发布策略

Nginx 遵循大约每年发布一个稳定主版本的节奏,每个稳定版本会维护约 18 个月的安全更新。建议生产环境使用最新的稳定版本。

ℹ️ 版本选择建议:

截至 2026 年,推荐使用 Nginx 1.26.x 或 1.28.x 稳定版本。

二、软件设计架构

2.1 总体架构设计

架构设计理念

Nginx 的架构设计核心思想是事件驱动 + 多进程模型,这是它能够高效处理大量并发连接的关键。与 Apache 的每请求一个进程/线程不同,Nginx 使用了 reactor 模式,通过少量的 worker 进程即可处理成千上万的并发连接。

┌─────────────────────────────────────────────────────────────────┐ │ Nginx 架构总览 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Master │ │ Worker 1 │ │ Worker N │ │ │ │ Process │────▶│ Process │ │ Process │ │ │ │ (管理进程) │ │ (工作进程) │ │ (工作进程) │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ │ │ │ │ │ ┌─────┴─────┐ ┌─────┴─────┐ │ │ │ │ Event │ │ Event │ │ │ │ │ Loop │ │ Loop │ │ │ │ └─────┬─────┘ └─────┬─────┘ │ │ │ │ │ │ │ ┌──────┴──────┐ ┌─────┴─────┐ ┌─────┴─────┐ │ │ │ Cache │ │ epoll/ │ │ epoll/ │ │ │ │ Manager │ │ kqueue │ │ kqueue │ │ │ └─────────────┘ └───────────┘ └───────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘

核心组件说明

组件职责数量
Master Process(主进程)读取和验证配置文件、创建/管理 worker 进程、发送信号、日志轮转管理1
Worker Process(工作进程)处理实际的客户端连接、执行事件循环、处理请求通常等于 CPU 核心数
Cache Loader(缓存加载器)启动时将缓存元数据加载到内存中1(按需)
Cache Manager(缓存管理器)定期检查缓存条目有效性,清理过期条目1(按需)

2.2 Master-Worker 进程模型详解

Master Process(主进程)

主进程以 root 权限运行,负责以下工作:

  • 读取配置文件:解析 nginx.conf 及其引用的配置文件
  • 创建 worker 进程:fork 出指定数量的 worker 子进程
  • 信号处理:
    • SIGTERM/SIGINT - 快速关闭
    • SIGQUIT - 优雅关闭
    • SIGHUP - 重新加载配置文件
    • SIGUSR1 - 重新打开日志文件
    • SIGUSR2 - 平滑升级(热重启)
  • 监控 worker 进程:当 worker 异常退出时自动重启新的 worker
  • 特权操作:绑定端口、创建 PID 文件等需要 root 权限的操作

Worker Process(工作进程)

工作进程以非特权用户身份运行(通常是 nginx 或 www-data),负责:

  • 事件循环:每个 worker 独立运行自己的事件循环
  • 连接处理:处理 TCP/UDP 连接的建立、数据传输、关闭
  • 请求处理:解析 HTTP 请求,调用相应的处理模块
  • 负载均衡竞争:多个 worker 通过 accept_mutex 或 reuseport 竞争新连接

┌─────────────────────────────────────────────────────────────┐ │ Master 进程管理流程 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ nginx -c /etc/nginx/nginx.conf │ │ │ │ │ ▼ │ │ ┌──────────────┐ │ │ │ fork() │ │ │ │ Master │ │ │ └──────┬───────┘ │ │ │ │ │ ┌────┼────┬────────┐ │ │ ▼ ▼ ▼ ▼ │ │ ┌───┐┌───┐┌───┐ ┌───┐ │ │ │ W1││ W2││ W3│ │ Wn│ ← Worker 进程(非特权用户) │ │ └───┘└───┘└───┘ └───┘ │ │ │ │ 信号传递: Master ──signal──▶ Worker │ │ Worker 退出: Worker ──exit──▶ Master (自动重启) │ │ │ └─────────────────────────────────────────────────────────────┘

进程间通信(IPC)

Nginx 使用以下方式进行进程间通信:

  • Unix Signal(信号):主进程向 worker 发送控制信号
  • Unix Domain Socket:用于 worker 之间的通信和共享数据
  • 共享内存:用于 worker 之间共享配置、状态等信息
  • 文件锁:用于 accept_mutex 互斥机制

2.3 事件驱动模型(Event-Driven)

事件驱动架构核心

Nginx 使用异步非阻塞 I/O + 多路复用的事件驱动模型,这是其高性能的关键所在。与传统同步阻塞 I/O 不同,事件驱动模型不会因为等待 I/O 而阻塞整个进程。

🔑 关键概念:

每个 worker 进程在同一时间只运行一个事件循环,但可以通过非阻塞 I/O 同时处理成千上万个连接。

I/O 多路复用机制

Nginx 支持多种操作系统提供的高效 I/O 多路复用机制:

操作系统I/O 多路复用机制特点
Linuxepoll时间复杂度 O(1),适合大规模连接
FreeBSD/macOSkqueue高效的 BSD 系统事件通知
Solaris/dev/pollSolaris 特有
所有平台select/poll通用但性能较差,作为备选

事件处理流程

┌─────────────────────────────────────────────────────┐ │ Worker 事件循环流程 │ ├─────────────────────────────────────────────────────┤ │ │ │ ┌──────────┐ │ │ │ 等待 │◄─────────────────────────┐ │ │ │ 事件 │ │ │ │ └────┬─────┘ │ │ │ │ (epoll_wait 返回) │ │ │ ▼ │ │ │ ┌──────────┐ │ │ │ │ 遍历 │ │ │ │ │ 就绪事件│ │ │ │ └────┬─────┘ │ │ │ │ │ │ │ ▼ │ │ │ ┌──────────┐ ┌──────────┐ │ │ │ │ 处理 │────▶│ 处理 │────... │ │ │ │ 事件 A │ │ 事件 B │ │ │ │ └────┬─────┘ └──────────┘ │ │ │ │ │ │ │ ▼ │ │ │ ┌──────────┐ │ │ │ │ 检查 │──── 没有更多事件 ────────┘ │ │ │ 定时器 │ │ │ └──────────┘ │ │ │ └─────────────────────────────────────────────────────┘

连接状态机

每个连接在 Nginx 中被表示为一个 ngx_connection_t 结构体,通过状态机管理其生命周期:

接受连接

→

读取请求头

→

解析请求

→

处理请求

→

发送响应

→

关闭/保持

每个阶段的处理函数都注册为事件回调,当 I/O 就绪时自动触发,避免了线程切换和锁竞争的开销。

2.4 内存管理机制

内存池(Memory Pool)

Nginx 使用了自定义的内存池管理系统,避免了频繁调用 malloc/free 带来的性能开销和内存碎片问题。

  • 池化分配:预先分配一块大内存,后续从小块中分配
  • 自动释放:请求处理完成后,整个内存池一次性释放
  • 对齐分配:内存按指针对齐,提高 CPU 缓存命中率
  • 大内存处理:超过池大小的分配使用系统 malloc,记录在链表中随池释放

内存池结构

struct ngx_pool_s {
    ngx_pool_data_t    d;        /* 内存池数据 */
    size_t             max;      /* 最大块大小 */
    ngx_pool_t        *current;  /* 当前分配池 */
    ngx_chain_t       *chain;    /* 大内存链表 */
    ngx_pool_large_t  *large;    /* 大内存分配列表 */
    ngx_pool_cleanup_t *cleanup; /* 清理回调 */
    ngx_log_t         *log;      /* 日志 */
};

缓冲区管理

Nginx 使用 ngx_buf_t 结构体管理数据缓冲区,支持:

  • 内存缓冲区:数据存储在内存中
  • 文件缓冲区:数据引用磁盘文件,使用 sendfile 零拷贝传输
  • 链式缓冲区:通过 ngx_chain_t 将多个缓冲区串联

⚡ Zero-Copy(零拷贝):

Nginx 在发送静态文件时,使用 sendfile() 系统调用,数据直接从磁盘文件传输到网络套接字,避免了内核空间到用户空间的拷贝,极大提升了性能。

2.5 请求处理流水线

11 个处理阶段(Phases)

Nginx 将 HTTP 请求的处理过程分为 11 个阶段(Phases),每个阶段执行特定的功能,模块可以在对应阶段注册处理函数:

阶段名称功能
1POST_READ读取请求后首先执行,如获取客户端真实IP
2SERVER_REWRITEserver 级别的 URL 重写
3FIND_CONFIG根据 URI 查找匹配的 location(不可插入模块)
4REWRITElocation 级别的 URL 重写
5POST_REWRITEURL 重写后重新查找 location(不可插入模块)
6PREACCESS访问控制前准备,如限流、连接限制
7ACCESS访问控制,如 allow/deny 规则
8POST_ACCESS访问控制后处理(如 satisfy any)
9PRECONTENT内容处理前的准备
10CONTENT生成响应内容(核心阶段)
11LOG记录日志

请求进入 │ ▼ POST_READ ──▶ SERVER_REWRITE ──▶ FIND_CONFIG ──▶ REWRITE │ ┌─────────────────────────────────────────────────┘ ▼ POST_REWRITE ──▶ PREACCESS ──▶ ACCESS ──▶ POST_ACCESS │ ┌─────────────────────────────────────────────────┘ ▼ PRECONTENT ──▶ CONTENT ──▶ LOG ──▶ 请求完成

2.6 配置解析与继承机制

配置解析流程

  1. 配置文件读取:主进程读取 nginx.conf
  2. 词法分析:将配置文件解析为 token 流
  3. 语法分析:构建配置命令树(command tree)
  4. 命令执行:按照作用域依次执行配置指令
  5. 配置合并:将不同级别的配置进行合并

配置继承(Merge)机制

Nginx 的配置具有层级继承关系:

main (全局配置) │ ├── http { } (HTTP 协议级) │ │ │ ├── server { } (虚拟主机级) │ │ │ │ │ └── location { } (URI 路径级) │ │ │ └── upstream { } (上游服务器组) │ ├── events { } (事件处理级) │ ├── mail { } (邮件代理级) │ └── stream { } (TCP/UDP 代理级)

继承规则:子级配置默认继承父级配置,如果子级配置中显式定义了相同的指令,则覆盖父级配置。

配置指令类型

  • NGX_MAIN_CONF:全局配置(如 worker_processes)
  • NGX_HTTP_MAIN_CONF:HTTP 主配置
  • NGX_HTTP_SRV_CONF:Server 配置
  • NGX_HTTP_LOC_CONF:Location 配置
  • NGX_HTTP_UPS_CONF:Upstream 配置

2.7 连接管理与事件通知

连接池

Nginx 预先分配固定数量的连接对象(由 worker_connections 指令控制),所有连接从连接池中获取,用完归还,避免了动态内存分配的开销。

struct ngx_connection_s {
    void               *data;       /* 关联的数据 */
    ngx_event_t        *read;       /* 读事件 */
    ngx_event_t        *write;      /* 写事件 */
    ngx_socket_t        fd;         /* 文件描述符 */
    ngx_recv_pt         recv;       /* 接收函数 */
    ngx_send_pt         send;       /* 发送函数 */
    struct sockaddr    *sockaddr;   /* 对端地址 */
    socklen_t           socklen;
    ngx_str_t           addr_text;  /* 地址文本 */
    /* ... */
};

连接竞争机制

多个 worker 进程监听同一端口时,需要一种机制来协调谁接受新连接:

  • accept_mutex(传统方式):worker 通过互斥锁竞争 accept 权限,只有获得锁的 worker 才能调用 accept()
  • reuseport(推荐方式,Linux 3.9+):内核级别的连接分配,每个 worker 独立监听端口,由内核公平分配连接,性能更优

🚀 性能提示:

在 Linux 3.9+ 环境下,建议启用 reuseport 以获得更好的连接分配性能:

listen 80 reuseport;

三、安装与部署

3.1 Linux 系统安装

Ubuntu/Debian 安装

# 更新软件包索引
sudo apt update

# 安装 Nginx
sudo apt install nginx

# 启动 Nginx
sudo systemctl start nginx

# 设置开机自启
sudo systemctl enable nginx

# 查看状态
sudo systemctl status nginx

使用官方仓库安装(推荐,获取最新版本)

# 安装先决条件
sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring

# 导入官方签名密钥
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
    | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

# 添加稳定版仓库
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
    | sudo tee /etc/apt/sources.list.d/nginx.list

# 更新并安装
sudo apt update
sudo apt install nginx

CentOS/RHEL/Rocky Linux 安装

# 使用 EPEL 仓库
sudo yum install epel-release
sudo yum install nginx

# 或使用官方仓库,创建 /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key

sudo yum install nginx

验证安装

# 检查版本
nginx -v

# 测试配置文件语法
sudo nginx -t

# 输出示例:
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

3.2 从源码编译安装

准备工作

# 安装编译工具和依赖
# Ubuntu/Debian
sudo apt install build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev \
    libssl-dev libgd-dev libgeoip-dev libxml2-dev libxslt1-dev

# CentOS/RHEL
sudo yum groupinstall "Development Tools"
sudo yum install pcre-devel zlib-devel openssl-devel gd-devel \
    geoip-devel libxml2-devel libxslt-devel

下载并编译

# 下载源码
wget https://nginx.org/download/nginx-1.26.2.tar.gz
tar -zxvf nginx-1.26.2.tar.gz
cd nginx-1.26.2

# 配置编译选项
./configure \
    --prefix=/usr/local/nginx \
    --sbin-path=/usr/local/nginx/sbin/nginx \
    --conf-path=/usr/local/nginx/conf/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=/var/lock/nginx.lock \
    --user=nginx \
    --group=nginx \
    --with-http_ssl_module \
    --with-http_v2_module \
    --with-http_v3_module \
    --with-http_realip_module \
    --with-http_gzip_static_module \
    --with-http_stub_status_module \
    --with-http_image_filter_module \
    --with-http_geoip_module \
    --with-stream \
    --with-stream_ssl_module \
    --with-threads \
    --with-file-aio

# 编译安装
make -j$(nproc)
sudo make install

创建 systemd 服务文件

sudo nano /etc/systemd/system/nginx.service

[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/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

# 重新加载并启用
sudo systemctl daemon-reload
sudo systemctl enable nginx

3.3 Docker 容器化部署

基本使用

# 拉取官方镜像
docker pull nginx:latest

# 运行容器
docker run -d --name nginx \
    -p 80:80 \
    -p 443:443 \
    -v /path/to/nginx.conf:/etc/nginx/nginx.conf:ro \
    -v /path/to/conf.d:/etc/nginx/conf.d:ro \
    -v /path/to/ssl:/etc/nginx/ssl:ro \
    -v /path/to/html:/usr/share/nginx/html:ro \
    nginx:latest

Docker Compose 配置

version: '3.8'

services:
  nginx:
    image: nginx:1.26-alpine
    container_name: nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./conf.d:/etc/nginx/conf.d:ro
      - ./ssl:/etc/nginx/ssl:ro
      - ./html:/usr/share/nginx/html:ro
      - ./logs:/var/log/nginx
    restart: unless-stopped
    networks:
      - webnet

networks:
  webnet:
    driver: bridge

自定义 Dockerfile

FROM nginx:1.26-alpine

# 复制自定义配置
COPY nginx.conf /etc/nginx/nginx.conf
COPY conf.d/ /etc/nginx/conf.d/

# 复制静态文件
COPY html/ /usr/share/nginx/html/

# 安装额外工具(可选)
RUN apk add --no-cache curl

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost/ || exit 1

EXPOSE 80 443

CMD ["nginx", "-g", "daemon off;"]

四、配置详解

4.1 配置文件结构

主要配置文件

# /etc/nginx/nginx.conf - 主配置文件

# ===== 全局块 =====
user nginx;                    # 运行用户
worker_processes auto;         # worker 进程数(auto=CPU 核心数)
worker_rlimit_nofile 65535;   # 每个 worker 最大打开文件数
error_log /var/log/nginx/error.log warn;  # 错误日志
pid /run/nginx.pid;            # PID 文件

# ===== events 块 =====
events {
    worker_connections 4096;   # 每个 worker 最大并发连接数
    use epoll;                 # I/O 多路复用模型
    multi_accept on;           # 一次接受多个连接
}

# ===== http 块 =====
http {
    include /etc/nginx/mime.types;       # MIME 类型映射
    default_type application/octet-stream;

    # 日志格式
    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 /var/log/nginx/access.log main;

    # 性能优化
    sendfile on;               # 启用零拷贝
    tcp_nopush on;             # 启用 TCP_NOPUSH
    tcp_nodelay on;            # 启用 TCP_NODELAY
    keepalive_timeout 65;      # 长连接超时
    types_hash_max_size 2048;  # 类型哈希表大小
    client_max_body_size 50m;  # 客户端最大请求体

    # Gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json
               application/javascript text/xml
               application/xml application/xml+rss text/javascript;

    # 包含子配置
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

指令语法

  • 简单指令:指令名 参数;
  • 块指令:指令名 { ... }
  • 注释:# 注释内容
  • 变量:$变量名(如 $remote_addr, $uri)

4.2 Server 虚拟主机配置

Server Block 基本结构

server {
    # 监听端口和地址
    listen 80;
    listen [::]:80;              # IPv6
    listen 443 ssl http2;        # HTTPS + HTTP/2

    # 服务器名称(支持通配符和正则表达式)
    server_name example.com www.example.com;
    server_name *.example.com;               # 通配符
    server_name ~^(?<subdomain>.+)\.example\.com$;  # 正则

    # 根目录
    root /var/www/example.com/html;

    # 默认首页
    index index.html index.htm index.php;

    # 字符集
    charset utf-8;

    # 访问日志
    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;

    # location 块
    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # 错误页面
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

server_name 匹配规则

匹配类型示例说明
精确匹配example.com完全匹配域名
前缀通配符*.example.com匹配所有子域名
后缀通配符example.*匹配所有后缀
正则表达式~^www.(.+).com$正则匹配(~ 区分大小写,~* 不区分)

优先级顺序:精确匹配 > 前缀通配符 > 后缀通配符 > 正则表达式

4.3 Location 匹配规则详解

Location 语法

location [=|~|~*|^~|@] /uri { ... }

匹配修饰符

修饰符含义示例
=精确匹配location = /api/health
^~前缀匹配(匹配后停止正则搜索)location ^~ /static/
~正则匹配(区分大小写)location ~ .php$
~*正则匹配(不区分大小写)location ~* .(jpg|png|gif)$
@命名 location(用于内部重定向)location @fallback
(无)普通前缀匹配location /images/

匹配优先级(从高到低)

  1. = 精确匹配
  2. ^~ 前缀匹配(优先于正则)
  3. ~ 或 ~* 正则匹配(按配置文件顺序)
  4. 普通前缀匹配(选择最长匹配)

配置示例

# 精确匹配首页
location = / {
    root /var/www/html;
    index index.html;
}

# 静态文件 - 前缀匹配,不再检查正则
location ^~ /static/ {
    alias /var/www/static/;
    expires 30d;
    add_header Cache-Control "public, immutable";
}

# 图片文件 - 正则匹配
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
    expires 30d;
    access_log off;
    add_header Cache-Control "public";
}

# API 路由
location ~ ^/api/v1/ {
    proxy_pass http://api_backend;
}

# 所有其他请求
location / {
    try_files $uri $uri/ /index.html;
}

⚠️ 常见陷阱:

location 的正则匹配是按配置文件中的顺序匹配的,第一个匹配的正则表达式生效,而非最长匹配。因此应将更具体的正则放在前面。

4.4 常用指令速查

文件服务相关

指令作用示例
root指定文件根目录(会拼接 URI)root /var/www/html;
alias指定文件目录(替换 URI)alias /var/www/static/;
index默认首页文件列表index index.html index.php;
try_files尝试查找文件,失败时回退try_files $uri $uri/ =404;
autoindex启用目录列表autoindex on;

控制流程指令

指令作用
return直接返回状态码和/或 URL
rewriteURL 重写(支持正则)
if条件判断
set设置变量
map创建变量映射

rewrite 指令详解

# 语法: rewrite regex replacement [flag];

# flag 选项:
# last    - 停止当前处理,用新 URI 重新匹配 location
# break   - 停止当前 rewrite 规则集的处理
# redirect - 返回 302 临时重定向
# permanent - 返回 301 永久重定向

# 示例:
# HTTP 转 HTTPS
rewrite ^(.*)$ https://$host$1 permanent;

# 旧 URL 重定向
rewrite ^/old-page$ /new-page permanent;

# 动态 URL 重写
rewrite ^/user/(\d+)$ /user.php?id=$1 last;

map 指令示例

# 在 http 块中定义
map $http_user_agent $is_mobile {
    default 0;
    "~*mobile|android|iphone|ipad" 1;
}

map $uri $new_uri {
    default $uri;
    "~^/blog/(.*)" /articles/$1;
    "~^/news/(.*)" /press/$1;
}

# 在 server/location 中使用
server {
    if ($is_mobile) {
        rewrite ^ /mobile$uri;
    }
}

五、反向代理与负载均衡

5.1 反向代理配置

基本反向代理

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;

        # 传递客户端信息
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

完整的反向代理配置

server {
    listen 80;
    server_name app.example.com;

    # 代理超时设置
    proxy_connect_timeout 30s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;

    # 代理缓冲区
    proxy_buffering on;
    proxy_buffer_size 16k;
    proxy_buffers 4 32k;
    proxy_busy_buffers_size 64k;

    # 临时文件(大响应体写入磁盘)
    proxy_temp_file_write_size 64k;
    proxy_max_temp_file_size 1024m;

    # WebSocket 支持
    location /ws {
        proxy_pass http://websocket_backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400s;
    }

    # API 代理
    location /api/ {
        proxy_pass http://api_servers/;  # 注意末尾斜杠

        # 错误处理
        proxy_intercept_errors on;
        error_page 502 503 504 = @fallback;
    }

    location @fallback {
        proxy_pass http://backup_server;
    }
}

proxy_pass URL 末尾斜杠的区别

📝 重要区别:

例如:location /api/ 匹配请求 /api/users • 无斜杠:后端收到 /api/users • 有斜杠:后端收到 /users

5.2 Upstream 负载均衡

Upstream 配置

# 定义上游服务器组
upstream backend {
    # 负载均衡算法(默认为轮询)
    # 可用: ip_hash, hash, least_conn, random

    server 192.168.1.10:8080 weight=5;  # 权重
    server 192.168.1.11:8080 weight=3;
    server 192.168.1.12:8080 backup;     # 备份服务器
    server 192.168.1.13:8080 down;       # 标记为下线

    # 长连接(与后端保持的连接数)
    keepalive 32;
    keepalive_timeout 60s;
    keepalive_requests 1000;
}

负载均衡算法

轮询(Round Robin)

默认算法,按顺序将请求分配给服务器,支持权重。

upstream backend {
    server 10.0.0.1:80;
    server 10.0.0.2:80;
}

IP Hash

根据客户端 IP 的 hash 值分配,保证同一客户端始终访问同一服务器(会话保持)。

upstream backend {
    ip_hash;
    server 10.0.0.1:80;
    server 10.0.0.2:80;
}

Least Connections

将请求分配给当前活跃连接数最少的服务器。

upstream backend {
    least_conn;
    server 10.0.0.1:80;
    server 10.0.0.2:80;
}

Hash(自定义键)

基于自定义键值的 hash 分配,适合缓存场景。

upstream backend {
    hash $request_uri consistent;
    server 10.0.0.1:80;
    server 10.0.0.2:80;
}

健康检查

upstream backend {
    server 10.0.0.1:80 max_fails=3 fail_timeout=30s;
    server 10.0.0.2:80 max_fails=3 fail_timeout=30s;
    server 10.0.0.3:80 max_fails=3 fail_timeout=30s;
}
# max_fails=N: 在 fail_timeout 内允许的最大失败次数
# fail_timeout=T: 失败统计的时间窗口,也是服务器被标记不可用后的冷却时间

使用 upstream 的完整配置

upstream app_backend {
    least_conn;
    server 10.0.0.1:8080 weight=5 max_fails=3 fail_timeout=30s;
    server 10.0.0.2:8080 weight=3 max_fails=3 fail_timeout=30s;
    server 10.0.0.3:8080 backup;
    keepalive 32;
}

server {
    listen 80;
    server_name app.example.com;

    location / {
        proxy_pass http://app_backend;

        # 使用 HTTP/1.1 以支持 keepalive
        proxy_http_version 1.1;
        proxy_set_header Connection "";

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

5.3 代理缓存配置

代理缓存

# 在 http 块中定义缓存路径
proxy_cache_path /var/cache/nginx/proxy levels=1:2
    keys_zone=my_cache:10m      # 共享内存区域名:大小
    max_size=10g                 # 最大缓存大小
    inactive=60m                 # 不活跃条目过期时间
    use_temp_path=off;           # 不使用临时路径

# 在 server/location 中使用
server {
    location / {
        proxy_pass http://backend;

        # 启用缓存
        proxy_cache my_cache;
        proxy_cache_valid 200 302 10m;   # 200/302 响应缓存 10 分钟
        proxy_cache_valid 404 1m;        # 404 响应缓存 1 分钟
        proxy_cache_valid any 5m;        # 其他响应缓存 5 分钟

        # 缓存键
        proxy_cache_key "$scheme$request_method$host$request_uri";

        # 缓存控制
        proxy_cache_use_stale error timeout updating http_500 http_502
            http_503 http_504;
        proxy_cache_lock on;
        proxy_cache_lock_timeout 5s;

        # 添加缓存状态头
        add_header X-Cache-Status $upstream_cache_status;

        # 绕过缓存的条件
        proxy_cache_bypass $http_cache_control $cookie_nocache;
        proxy_no_cache $http_pragma $http_authorization;
    }
}

# $upstream_cache_status 可能的值:
# HIT     - 缓存命中
# MISS    - 缓存未命中
# EXPIRED - 缓存已过期
# STALE   - 返回过期缓存(后端不可用时)
# UPDATING - 缓存正在更新
# BYPASS  - 缓存被绕过

FastCGI 缓存(适用于 PHP 等)

fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2
    keys_zone=php_cache:10m max_size=1g inactive=60m;

server {
    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php-fpm.sock;
        fastcgi_index index.php;

        fastcgi_cache php_cache;
        fastcgi_cache_valid 200 10m;
        fastcgi_cache_key "$scheme$request_method$host$request_uri";

        fastcgi_cache_use_stale error timeout updating;
        add_header X-FastCGI-Cache $upstream_cache_status;

        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

六、SSL/TLS 配置

6.1 HTTPS 基本配置

SSL 证书配置

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name example.com www.example.com;

    # SSL 证书配置
    ssl_certificate /etc/nginx/ssl/example.com.crt;      # 证书文件(PEM 格式)
    ssl_certificate_key /etc/nginx/ssl/example.com.key;   # 私钥文件

    # 或使用 ECDSA 证书
    # ssl_certificate /etc/nginx/ssl/ecdsa.crt;
    # ssl_certificate_key /etc/nginx/ssl/ecdsa.key;

    # SSL 协议和加密套件
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;  # TLS 1.3 推荐设为 off

    # SSL 会话缓存(提升性能)
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;  # 安全起见可关闭

    # DH 参数(增强密钥交换安全)
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/nginx/ssl/chain.pem;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # HSTS (HTTP Strict Transport Security)
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

    # 其他安全头
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # 网站内容
    root /var/www/example.com/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

HTTP 到 HTTPS 重定向

# 方法一:return(推荐,性能更好)
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

# 方法二:rewrite
server {
    listen 80;
    server_name example.com www.example.com;
    rewrite ^(.*)$ https://$host$1 permanent;
}

6.2 Let's Encrypt 免费证书配置

使用 Certbot 自动获取证书

# 安装 Certbot 和 Nginx 插件
sudo apt install certbot python3-certbot-nginx  # Debian/Ubuntu
sudo yum install certbot python3-certbot-nginx  # CentOS/RHEL

# 自动获取证书并配置 Nginx
sudo certbot --nginx -d example.com -d www.example.com

# 仅获取证书(手动配置)
sudo certbot certonly --webroot -w /var/www/html -d example.com

# 使用 DNS 验证(适用于通配符证书)
sudo certbot certonly --manual --preferred-challenges dns -d "*.example.com"

# 测试自动续期
sudo certbot renew --dry-run

# 证书路径(Let's Encrypt 默认)
# 证书: /etc/letsencrypt/live/example.com/fullchain.pem
# 私钥: /etc/letsencrypt/live/example.com/privkey.pem

配合 Certbot 的 Nginx 配置

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # Let's Encrypt 验证路径(续期时需要)
    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    # 其余配置...
    location / {
        root /var/www/example.com/html;
    }
}

server {
    listen 80;
    server_name example.com www.example.com;

    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

生成 DH 参数

# 生成 2048 位 DH 参数(推荐)
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

# 生成 4096 位 DH 参数(更安全但更慢)
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096

6.3 HTTP/2 和 HTTP/3 (QUIC) 配置

HTTP/2 配置

server {
    listen 443 ssl;
    http2 on;  # Nginx 1.25.1+ 新语法
    # 或旧语法: listen 443 ssl http2;

    server_name example.com;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    # HTTP/2 特定优化
    # 多路复用默认启用,无需额外配置
    # 服务器推送(可选)
    # http2_push /static/style.css;
    # http2_push /static/app.js;
}

HTTP/3 (QUIC) 配置(Nginx 1.25+)

server {
    # QUIC/HTTP3 监听
    listen 443 quic reuseport;
    listen 443 ssl;
    http2 on;

    server_name example.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    # 告知客户端支持 HTTP/3
    add_header Alt-Svc 'h3=":443"; ma=86400';

    location / {
        root /var/www/html;
    }
}

🌐 HTTP/3 优势:

基于 UDP 的 QUIC 协议,解决了 TCP 的队头阻塞问题,连接建立更快(0-RTT),在弱网环境下性能显著优于 TCP。

七、性能优化

7.1 系统级调优

操作系统内核参数优化

# /etc/sysctl.conf - Linux 内核参数优化

# 文件系统
fs.file-max = 2097152
fs.inotify.max_user_watches = 524288

# 网络优化
net.core.somaxconn = 65535          # 监听队列最大长度
net.core.netdev_max_backlog = 65535 # 网络设备积压
net.core.rmem_max = 16777216       # 接收缓冲区最大
net.core.wmem_max = 16777216       # 发送缓冲区最大
net.core.rmem_default = 262144
net.core.wmem_default = 262144

# TCP 优化
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_tw_reuse = 1          # 允许重用 TIME_WAIT 连接
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.ip_local_port_range = 1024 65535

# 连接跟踪
net.netfilter.nf_conntrack_max = 1000000

# 应用修改
# sudo sysctl -p

文件描述符限制

# /etc/security/limits.conf
nginx  soft  nofile  65535
nginx  hard  nofile  65535
nginx  soft  nproc   65535
nginx  hard  nproc   65535

# 或在 systemd 服务文件中设置
# [Service]
# LimitNOFILE=65535
# LimitNPROC=65535

Nginx 配置中的关键参数

# 全局配置
worker_processes auto;        # 等于 CPU 核心数
worker_rlimit_nofile 65535;  # 每个 worker 最大文件描述符数
worker_cpu_affinity auto;     # CPU 亲和性(自动绑定)

# events 块
events {
    worker_connections 4096;   # 每 worker 最大并发连接
    use epoll;                 # 最佳 I/O 模型
    multi_accept on;           # 批量接受连接
    accept_mutex off;          # 使用 reuseport 时关闭
}

# http 块
http {
    sendfile on;               # 零拷贝传输
    tcp_nopush on;             # 合并小数据包
    tcp_nodelay on;            # 禁用 Nagle 算法
    keepalive_timeout 65;      # 长连接超时
    keepalive_requests 1000;   # 单连接最大请求数

    # 连接限制
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    limit_req_zone $binary_remote_addr zone=req:10m rate=10r/s;
}

7.2 静态文件优化

Sendfile 与零拷贝

# 启用 sendfile(内核直接从文件发送数据到网络)
sendfile on;

# 启用 aio(异步 I/O,适用于大文件)
aio on;
directio 512;  # 大于 512 字节的文件使用直接 I/O

Gzip 压缩优化

# 在 http 或 server 块中
gzip on;                    # 启用 gzip
gzip_vary on;               # 添加 Vary: Accept-Encoding 头
gzip_proxied any;           # 对所有代理请求压缩
gzip_comp_level 5;          # 压缩级别 (1-9),5 是较好的平衡
gzip_min_length 256;        # 最小压缩大小(避免压缩小文件)
gzip_buffers 16 8k;         # 压缩缓冲区

# 需要压缩的 MIME 类型
gzip_types
    text/plain
    text/css
    text/javascript
    text/xml
    application/json
    application/javascript
    application/x-javascript
    application/xml
    application/xml+rss
    application/vnd.ms-fontobject
    font/opentype
    image/svg+xml
    image/x-icon;

浏览器缓存控制

# 静态资源长缓存
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp|css|js|woff2?|ttf|eot)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    access_log off;
}

# HTML 文件短缓存
location ~* \.html?$ {
    expires 1h;
    add_header Cache-Control "public, must-revalidate";
}

# API 响应不缓存
location /api/ {
    add_header Cache-Control "no-store, no-cache, must-revalidate";
    add_header Pragma "no-cache";
}

Open File Cache

# 缓存文件元数据(减少 stat 系统调用)
open_file_cache max=10000 inactive=60s;
open_file_cache_valid 60s;       # 验证缓存有效性的间隔
open_file_cache_min_uses 2;      # 文件最少使用次数才缓存
open_file_cache_errors on;       # 缓存文件错误(404等)

7.3 限流与流量控制

连接数限制(limit_conn)

# 在 http 块中定义区域
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn_zone $server_name zone=perserver:10m;

# 在 server/location 中使用
server {
    # 每个 IP 最多 10 个并发连接
    limit_conn addr 10;

    # 每个虚拟主机最多 1000 个并发连接
    limit_conn perserver 1000;

    # 超限返回状态码
    limit_conn_status 503;
    limit_conn_log_level warn;
}

请求速率限制(limit_req)

# 在 http 块中定义区域
# rate=10r/s 表示每秒 10 个请求
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;

# 在 server/location 中使用
server {
    # API 限流:突发允许 20 个,无延迟处理
    location /api/ {
        limit_req zone=api_limit burst=20 nodelay;
        limit_req_status 429;
        proxy_pass http://api_backend;
    }

    # 登录接口更严格的限流
    location /login {
        limit_req zone=login_limit burst=5 nodelay;
        proxy_pass http://auth_backend;
    }

    # 白名单排除
    location /admin/ {
        # 不应用限流(通过 geo 模块实现白名单)
        limit_req zone=api_limit burst=100 nodelay;
    }
}

# 使用 geo 模块创建白名单
geo $limit_req {
    default 1;
    10.0.0.0/8 0;       # 内网不限流
    192.168.0.0/16 0;   # 内网不限流
}

# 条件限流
map $limit_req $limit_key {
    0 "";
    1 $binary_remote_addr;
}

limit_req_zone $limit_key zone=conditional:10m rate=10r/s;

八、安全加固

8.1 安全基础配置

隐藏版本信息

http {
    # 隐藏 Nginx 版本号
    server_tokens off;

    # 修改 Server 头(需要编译时修改或 More Headers 模块)
    more_set_headers 'Server: MyServer';
}

禁止目录遍历和信息泄露

# 禁止目录列表
autoindex off;

# 禁止访问隐藏文件
location ~ /\. {
    deny all;
    access_log off;
    log_not_found off;
}

# 禁止访问敏感文件
location ~* \.(env|git|svn|htaccess|htpasswd|ini|log|sh|conf|bak)$ {
    deny all;
}

# 禁止访问备份文件
location ~ ~$ {
    deny all;
}

访问控制

# IP 黑白名单
location /admin/ {
    # 白名单模式
    allow 10.0.0.0/8;
    allow 192.168.1.100;
    deny all;

    # 或使用黑名单模式
    # deny 10.10.10.0/24;
    # allow all;
}

# HTTP Basic 认证
location /admin/ {
    auth_basic "Admin Area";
    auth_basic_user_file /etc/nginx/.htpasswd;

    # 同时限制 IP
    allow 192.168.1.0/24;
    deny all;
    satisfy all;  # 必须同时满足 IP 和认证
}

# 生成密码文件
# htpasswd -c /etc/nginx/.htpasswd admin

安全头配置

# 全局安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';" always;

8.2 防御常见攻击

防御 CC 攻击

# 组合多种限流策略
http {
    # 正常请求限流
    limit_req_zone $binary_remote_addr zone=normal:10m rate=30r/s;

    # 特殊路径更严格
    limit_req_zone $binary_remote_addr zone=strict:10m rate=5r/s;

    # 连接数限制
    limit_conn_zone $binary_remote_addr zone=conn:10m;

    # 使用 geo 模块封禁恶意 IP
    geo $blocked_ip {
        default 0;
        # 已知恶意 IP 段
        203.0.113.0/24 1;
        198.51.100.0/24 1;
    }

    server {
        # 封禁恶意 IP
        if ($blocked_ip) {
            return 403;
        }

        # 连接数限制
        limit_conn conn 50;

        # 正常请求限流
        limit_req zone=normal burst=50 nodelay;

        # 敏感路径更严格
        location ~* (login|register|search|api) {
            limit_req zone=strict burst=10 nodelay;
        }

        # 检测异常 User-Agent
        if ($http_user_agent ~* (nikto|sqlmap|nmap|masscan|dirbuster)) {
            return 403;
        }
    }
}

防御 SQL 注入和 XSS

# 在 server 或 location 块中
# 检测 URL 中的 SQL 注入模式
if ($query_string ~* "(union.*select|insert.*into|delete.*from|drop.*table|update.*set|benchmark\(|sleep\()" ) {
    return 403;
}

# 检测常见的 XSS 攻击
if ($query_string ~* "(<|%3C).*script.*(>|%3E)") {
    return 403;
}

# 更安全的做法:使用 WAF(如 ModSecurity)
# 或使用 Nginx 的 njs 模块进行请求过滤

防御慢速攻击(Slowloris)

# 设置超时时间
client_header_timeout 10s;
client_body_timeout 10s;
send_timeout 10s;

# 限制请求头大小
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;

# 限制请求体大小
client_max_body_size 10m;

# 连接限制
keepalive_timeout 15s;
keepalive_requests 100;

九、模块系统

9.1 模块架构与分类

模块分类

Nginx 的功能通过模块化实现,主要分为以下几类:

核心模块(Core)

提供基础功能,如事件处理、进程管理、配置解析。

events

http

mail

stream

事件模块(Event)

实现不同的 I/O 多路复用机制。

epoll

kqueue

select

poll

HTTP 模块

处理 HTTP 协议相关的各种功能。

proxy

gzip

ssl

rewrite

第三方模块

社区开发的扩展模块,需要编译时加入。

headers-more

echo

lua

njs

模块加载方式

  • 静态编译:模块直接编译到 Nginx 二进制文件中
  • 动态加载(Nginx 1.9.11+):使用 load_module 指令动态加载 .so 文件
# 动态加载模块
load_module modules/ngx_http_image_filter_module.so;
load_module modules/ngx_http_geoip_module.so;
load_module /usr/lib/nginx/modules/ndk_http_module.so;
load_module /usr/lib/nginx/modules/ngx_http_lua_module.so;

9.2 常用第三方模块

Nginx 官方动态模块

模块名功能
ngx_http_geoip_module基于 GeoIP 数据库的地理位置识别
ngx_http_image_filter_module图片实时处理(缩放、裁剪、旋转)
ngx_http_xslt_moduleXML/XSLT 转换
ngx_stream_moduleTCP/UDP 四层代理
ngx_http_perl_module嵌入 Perl 脚本

社区第三方模块

模块名功能安装方式
headers-more-nginx-module修改/添加/删除响应头编译时 --add-module
echo-nginx-moduleecho、sleep 等调试指令编译时 --add-module
lua-nginx-module (OpenResty)嵌入 Lua 脚本,实现复杂逻辑OpenResty 或编译
njs嵌入 JavaScript 脚本动态加载
ModSecurityWeb 应用防火墙(WAF)动态加载
brotliBrotli 压缩支持编译时 --add-module
pagespeed自动优化网页性能编译时 --add-module

十、高级应用场景

10.1 TCP/UDP 四层代理(Stream 模块)

TCP 反向代理

# 在 nginx.conf 顶层配置(与 http 同级)
stream {
    # 日志格式
    log_format stream_fmt '$remote_addr [$time_local] '
                          '$protocol $status $bytes_sent $bytes_received '
                          '$session_time "$upstream_addr"';
    access_log /var/log/nginx/stream.log stream_fmt;

    # MySQL 代理
    upstream mysql_backend {
        server 10.0.0.1:3306;
        server 10.0.0.2:3306 backup;
    }

    server {
        listen 3306;
        proxy_pass mysql_backend;
        proxy_connect_timeout 5s;
        proxy_timeout 300s;
    }

    # Redis 代理
    upstream redis_backend {
        hash $remote_addr consistent;
        server 10.0.0.10:6379;
        server 10.0.0.11:6379;
        server 10.0.0.12:6379;
    }

    server {
        listen 6379;
        proxy_pass redis_backend;
    }

    # SSH 代理
    server {
        listen 2222;
        proxy_pass 10.0.0.5:22;
        proxy_timeout 1h;
    }
}

UDP 代理

stream {
    # DNS 负载均衡
    upstream dns_servers {
        server 8.8.8.8:53;
        server 8.8.4.4:53;
        server 1.1.1.1:53;
    }

    server {
        listen 53 udp;
        proxy_pass dns_servers;
        proxy_responses 1;     # 期望的响应包数
        proxy_timeout 5s;
    }
}

SNI 路由(基于 TLS SNI 的流量分发)

stream {
    # 基于 SNI 将流量分发到不同的后端
    map $ssl_preread_server_name $backend {
        example.com      example_backend;
        api.example.com  api_backend;
        default          default_backend;
    }

    upstream example_backend {
        server 10.0.0.1:443;
    }

    upstream api_backend {
        server 10.0.0.2:443;
    }

    upstream default_backend {
        server 10.0.0.3:443;
    }

    server {
        listen 443;
        ssl_preread on;    # 预读 TLS 握手获取 SNI
        proxy_pass $backend;
    }
}

10.2 微服务网关配置

API 网关模式

# 各微服务的 upstream
upstream user_service {
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
}

upstream order_service {
    server 10.0.2.10:8080;
    server 10.0.2.11:8080;
}

upstream product_service {
    server 10.0.3.10:8080;
    server 10.0.3.11:8080;
}

upstream auth_service {
    server 10.0.4.10:8080;
}

# 公共代理配置
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Request-ID $request_id;
proxy_connect_timeout 5s;
proxy_read_timeout 30s;

server {
    listen 443 ssl http2;
    server_name api.example.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    # 限流
    limit_req zone=api_global burst=100 nodelay;

    # 用户服务
    location /api/users {
        proxy_pass http://user_service;
        limit_req zone=api_strict burst=20 nodelay;
    }

    # 订单服务
    location /api/orders {
        proxy_pass http://order_service;
        limit_req zone=api_strict burst=20 nodelay;
    }

    # 商品服务
    location /api/products {
        proxy_pass http://product_service;
    }

    # 认证服务
    location /api/auth {
        proxy_pass http://auth_service;
        limit_req zone=login_limit burst=5 nodelay;
    }

    # 健康检查端点
    location /health {
        access_log off;
        return 200 "OK\n";
        add_header Content-Type text/plain;
    }
}

A/B 测试配置

# 使用 split_clients 模块实现流量分割
split_clients "${remote_addr}" $ab_version {
    50%  "version_a";
    *    "version_b";
}

upstream app_a {
    server 10.0.0.1:8080;
}

upstream app_b {
    server 10.0.0.2:8080;
}

server {
    listen 80;
    server_name app.example.com;

    location / {
        if ($ab_version = "version_a") {
            proxy_pass http://app_a;
        }
        if ($ab_version = "version_b") {
            proxy_pass http://app_b;
        }

        # 添加标记头用于日志分析
        add_header X-AB-Version $ab_version;
    }
}

10.3 高可用与蓝绿部署

蓝绿部署

# 定义蓝色和绿色环境
upstream app_blue {
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
}

upstream app_green {
    server 10.0.0.3:8080;
    server 10.0.0.4:8080;
}

# 使用 map 或 geo 控制流量方向
map $cookie_deploy_version $backend {
    default     "app_blue";
    "green"     "app_green";
}

# 或者通过请求头控制(便于测试)
server {
    listen 80;

    location / {
        # 检查请求头
        if ($http_x_deploy_version = "green") {
            proxy_pass http://app_green;
            break;
        }

        # 默认使用蓝色环境
        proxy_pass http://app_blue;
    }
}

# 切换流量:修改 map 中的 default 值,然后 reload
# map $cookie_deploy_version $backend {
#     default     "app_green";   ← 改为绿色
#     "blue"      "app_blue";
# }

金丝雀发布(Canary Release)

# 将小比例流量导入新版本
split_clients "${request_id}" $canary {
    5%   "canary";     # 5% 流量到新版本
    *    "stable";     # 95% 流量到稳定版
}

upstream stable_backend {
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
}

upstream canary_backend {
    server 10.0.0.3:8080;  # 新版本
}

server {
    listen 80;

    location / {
        if ($canary = "canary") {
            proxy_pass http://canary_backend;
            break;
        }
        proxy_pass http://stable_backend;
    }
}

10.4 Nginx 与 Docker/Kubernetes 集成

Kubernetes Ingress Controller

# Kubernetes Ingress 资源示例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"
    nginx.ingress.kubernetes.io/rate-limit: "10"
    nginx.ingress.kubernetes.io/rate-limit-window: "1m"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - app.example.com
    secretName: app-tls
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend-service
            port:
              number: 80

Docker 动态配置(模板化)

# 使用 envsubst 动态生成配置
# nginx.template
server {
    listen ${LISTEN_PORT:-80};
    server_name ${SERVER_NAME:-localhost};

    location / {
        proxy_pass http://${BACKEND_HOST:-backend}:${BACKEND_PORT:-8080};
    }
}

# Dockerfile
FROM nginx:alpine
COPY nginx.template /etc/nginx/templates/default.conf.template
ENV LISTEN_PORT=80
ENV SERVER_NAME=example.com
ENV BACKEND_HOST=backend
ENV BACKEND_PORT=8080

# docker-compose.yml 中使用
# environment:
#   - SERVER_NAME=example.com
#   - BACKEND_HOST=app
#   - BACKEND_PORT=3000

十一、故障排查

11.1 常用诊断命令

基本检查

# 测试配置文件语法
nginx -t
nginx -T  # 测试并输出完整配置

# 查看 Nginx 进程
ps aux | grep nginx

# 查看端口占用
ss -tlnp | grep nginx
# 或
netstat -tlnp | grep nginx

# 查看 Nginx 编译参数
nginx -V

# 查看连接状态
ss -s

# 查看当前连接数
ss -tn state established | wc -l

# 查看各状态连接数
ss -tn | awk '{print $1}' | sort | uniq -c | sort -rn

日志分析

# 实时查看访问日志
tail -f /var/log/nginx/access.log

# 实时查看错误日志
tail -f /var/log/nginx/error.log

# 分析访问最多的 IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# 分析访问最多的 URL
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# 分析 HTTP 状态码分布
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

# 分析请求方法分布
awk '{print $6}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

# 查看带宽使用
awk '{sum+=$10} END {print sum/1024/1024 " MB"}' /var/log/nginx/access.log

性能诊断

# 查看 worker 进程资源使用
top -p $(pgrep -d, nginx)

# 查看文件描述符使用
ls -la /proc/$(pgrep -o nginx)/fd | wc -l

# 使用 strace 跟踪系统调用
strace -p  -c

# 使用 perf 分析性能瓶颈
perf record -g -p 
perf report

11.2 常见错误及解决方案

错误代码速查表

错误原因解决方案
502 Bad Gateway后端服务不可用或响应超时检查后端服务状态、端口、防火墙
504 Gateway Timeout后端响应超时增大 proxy_read_timeout,优化后端性能
413 Request Entity Too Large请求体超过限制增大 client_max_body_size
403 Forbidden权限不足或被 deny 规则拦截检查文件权限、allow/deny 规则
429 Too Many Requests触发限流调整 limit_req/limit_conn 配置

常见问题排查

问题:Worker 进程异常退出

# 检查错误日志
tail -100 /var/log/nginx/error.log

# 检查系统日志
journalctl -u nginx --since "1 hour ago"
dmesg | grep -i oom  # 检查 OOM Killer

问题:worker_connections are not enough

# 增加 worker_connections
events {
    worker_connections 8192;
}

# 同时确保系统文件描述符足够
worker_rlimit_nofile 16384;

问题:upstream timed out

# 增加超时时间
proxy_connect_timeout 30s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;

# 检查后端服务是否健康
curl -I http://backend_server:port/health

问题:SSL 证书错误

# 检查证书有效期
openssl x509 -in /etc/nginx/ssl/cert.pem -noout -dates

# 检查证书链完整性
openssl verify -CAfile /etc/nginx/ssl/chain.pem /etc/nginx/ssl/cert.pem

# 测试 SSL 配置
openssl s_client -connect example.com:443 -servername example.com

11.3 监控与告警

启用 Stub Status 模块

server {
    listen 8080;
    server_name localhost;

    location /nginx_status {
        stub_status on;
        access_log off;

        # 限制访问
        allow 127.0.0.1;
        allow 10.0.0.0/8;
        deny all;
    }
}

# 输出示例:
# Active connections: 291
# server accepts handled requests
#  16630948 16630948 31070465
# Reading: 6 Writing: 179 Waiting: 106

Prometheus 监控(使用 nginx-prometheus-exporter)

# Docker 运行 exporter
docker run -p 9113:9113 \
    nginx/nginx-prometheus-exporter:latest \
    --nginx.scrape-uri=http://nginx:8080/nginx_status

# 或使用 Nginx Plus 原生支持 Prometheus
# location /api/ {
#     api write=on;  # Nginx Plus API
# }

关键监控指标

  • 连接数:活跃连接数、等待连接数
  • 请求数:QPS、请求成功率
  • 状态码分布:2xx/3xx/4xx/5xx 比例
  • 响应时间:平均响应时间、P95/P99 延迟
  • 带宽使用:入站/出站流量
  • 错误率:5xx 错误比例
  • 上游健康:后端服务器健康状态

十二、最佳实践

12.1 配置文件组织规范

推荐目录结构

/etc/nginx/
├── nginx.conf              # 主配置文件
├── mime.types              # MIME 类型映射
├── conf.d/                 # 通用配置片段
│   ├── gzip.conf
│   ├── security.conf
│   └── logging.conf
├── sites-available/        # 所有站点配置(激活/未激活)
│   ├── example.com.conf
│   ├── api.example.com.conf
│   └── admin.example.com.conf
├── sites-enabled/          # 已激活的站点(软链接)
│   ├── example.com.conf -> ../sites-available/example.com.conf
│   └── api.example.com.conf -> ../sites-available/api.example.com.conf
├── upstreams/              # upstream 定义
│   ├── backend.conf
│   └── websocket.conf
├── ssl/                    # SSL 证书和密钥
│   ├── example.com.crt
│   ├── example.com.key
│   └── dhparam.pem
├── snippets/               # 可复用的配置片段
│   ├── ssl-params.conf
│   └── proxy-params.conf
└── maps/                   # map 定义
    └── geo-blocking.conf

配置片段复用

# /etc/nginx/snippets/ssl-params.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;

# /etc/nginx/snippets/proxy-params.conf
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";

# 在站点配置中引用
server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    include snippets/ssl-params.conf;

    location / {
        proxy_pass http://backend;
        include snippets/proxy-params.conf;
    }
}

12.2 运维自动化

平滑重载配置

# 测试配置后重载(推荐)
sudo nginx -t && sudo nginx -s reload

# 或
sudo systemctl reload nginx

零停机升级(Hot Upgrade)

#!/bin/bash
# Nginx 零停机升级脚本

OLD_PID=$(cat /run/nginx.pid)

# 1. 用新的二进制文件启动新的 master 进程
kill -USR2 $OLD_PID

# 2. 等待新的 master 进程创建 PID 文件
sleep 1
NEW_PID=$(cat /run/nginx.pid)

# 3. 让旧 master 进程优雅退出 worker
kill -WINCH $OLD_PID

# 4. 确认新进程工作正常后,让旧 master 退出
# kill -QUIT $OLD_PID

# 如果需要回滚:
# kill -HUP $OLD_PID   # 重新启动旧 worker
# kill -QUIT $NEW_PID  # 关闭新 master

自动化备份与部署脚本

#!/bin/bash
# Nginx 配置部署脚本

NGINX_DIR="/etc/nginx"
BACKUP_DIR="/backup/nginx"
DATE=$(date +%Y%m%d_%H%M%S)

# 创建备份
mkdir -p $BACKUP_DIR
cp -r $NGINX_DIR $BACKUP_DIR/nginx_backup_$DATE

# 同步新配置(从 Git 仓库)
cd /path/to/nginx-config-repo
git pull origin main

# 复制配置到 Nginx 目录
cp -r ./nginx/* $NGINX_DIR/

# 测试配置
if nginx -t 2>&1 | grep -q "syntax is ok"; then
    echo "配置测试通过,正在重载..."
    nginx -s reload
    echo "部署成功!"
else
    echo "配置测试失败,正在回滚..."
    rm -rf $NGINX_DIR
    cp -r $BACKUP_DIR/nginx_backup_$DATE $NGINX_DIR
    echo "已回滚到上一版本"
    exit 1
fi

Ansible 自动化管理

---
# Ansible Playbook: nginx-deploy.yml
- hosts: webservers
  become: yes
  tasks:
    - name: Copy nginx configuration
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        validate: 'nginx -t -c %s'
      notify: reload nginx

    - name: Copy site configurations
      template:
        src: "sites/{{ item }}.conf.j2"
        dest: "/etc/nginx/sites-available/{{ item }}.conf"
      loop: "{{ nginx_sites }}"
      notify: reload nginx

    - name: Enable sites
      file:
        src: "/etc/nginx/sites-available/{{ item }}.conf"
        dest: "/etc/nginx/sites-enabled/{{ item }}.conf"
        state: link
      loop: "{{ nginx_enabled_sites }}"
      notify: reload nginx

  handlers:
    - name: reload nginx
      service:
        name: nginx
        state: reloaded

12.3 完整生产环境配置模板

生产环境完整 nginx.conf

# ===== 全局配置 =====
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
worker_cpu_affinity auto;
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;

# ===== 事件配置 =====
events {
    worker_connections 4096;
    use epoll;
    multi_accept on;
    accept_mutex off;
}

# ===== HTTP 配置 =====
http {
    # --- 基本设置 ---
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    server_tokens off;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 1000;
    client_max_body_size 50m;
    types_hash_max_size 2048;
    server_names_hash_bucket_size 128;

    # --- 日志配置 ---
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    '"$http_x_forwarded_for" '
                    'rt=$request_time';

    access_log /var/log/nginx/access.log main buffer=16k flush=5s;

    # --- 压缩配置 ---
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 5;
    gzip_min_length 256;
    gzip_types text/plain text/css application/json
               application/javascript text/xml
               application/xml application/xml+rss
               text/javascript image/svg+xml;

    # --- 限流配置 ---
    limit_req_zone $binary_remote_addr zone=general:10m rate=30r/s;
    limit_req_zone $binary_remote_addr zone=api:10m rate=20r/s;
    limit_req_zone $binary_remote_addr zone=login:10m rate=5r/s;
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

    # --- 文件缓存 ---
    open_file_cache max=10000 inactive=60s;
    open_file_cache_valid 60s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    # --- 代理缓存路径 ---
    proxy_cache_path /var/cache/nginx/proxy levels=1:2
        keys_zone=static_cache:10m max_size=10g inactive=1d
        use_temp_path=off;

    # --- 上游服务器定义 ---
    include /etc/nginx/upstreams/*.conf;

    # --- 站点配置 ---
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*.conf;
}

生产站点配置示例

# /etc/nginx/sites-available/example.com.conf

# HTTP -> HTTPS 重定向
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

# HTTPS 主站
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name example.com www.example.com;

    # SSL 配置
    ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;
    include snippets/ssl-params.conf;

    # 根目录
    root /var/www/example.com/html;
    index index.html;

    # 安全头
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # 限流
    limit_req zone=general burst=50 nodelay;
    limit_conn conn_limit 100;

    # 静态文件
    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp|css|js|woff2?|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    # HTML 文件
    location ~* \.html?$ {
        expires 1h;
        add_header Cache-Control "public, must-revalidate";
    }

    # API 代理
    location /api/ {
        limit_req zone=api burst=30 nodelay;
        proxy_pass http://api_backend;
        include snippets/proxy-params.conf;
    }

    # 默认路由
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 健康检查
    location = /health {
        access_log off;
        return 200 "OK\n";
        add_header Content-Type text/plain;
    }

    # 禁止访问隐藏文件
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
}

# www 重定向到非 www
server {
    listen 443 ssl http2;
    server_name www.example.com;
    ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;
    return 301 https://example.com$request_uri;
}

12.4 Nginx 与主流技术栈集成

Nginx + Node.js

upstream nodejs_app {
    server 127.0.0.1:3000;
    keepalive 32;
}

server {
    listen 80;
    server_name nodeapp.example.com;

    location / {
        proxy_pass http://nodejs_app;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # WebSocket 支持
    location /socket.io/ {
        proxy_pass http://nodejs_app;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Nginx + Python (Gunicorn/uWSGI)

# Gunicorn
upstream gunicorn_app {
    server unix:/run/gunicorn.sock;
    # 或: server 127.0.0.1:8000;
}

server {
    listen 80;
    server_name python-app.example.com;

    location / {
        proxy_pass http://gunicorn_app;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # Django 静态文件
    location /static/ {
        alias /var/www/python-app/static/;
        expires 30d;
    }
}

# uWSGI
server {
    listen 80;
    server_name uwsgi-app.example.com;

    location / {
        uwsgi_pass unix:///run/uwsgi.sock;
        # 或: uwsgi_pass 127.0.0.1:3031;
        include uwsgi_params;
        uwsgi_param Host $host;
        uwsgi_param X-Real-IP $remote_addr;
    }
}

Nginx + PHP (PHP-FPM)

server {
    listen 80;
    server_name php-app.example.com;
    root /var/www/php-app/public;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        # 或: fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;

        # 性能优化
        fastcgi_buffer_size 32k;
        fastcgi_buffers 16 16k;
        fastcgi_busy_buffers_size 32k;
    }

    # Laravel 特定
    location ~ /\.(?!well-known).* {
        deny all;
    }
}

45.64.74.193

← 返回IT 技术 yicool 百科 · 🚀 Nginx 软件设计架构与详细教程

评论 0