Nginx 配置指南

78 阅读9分钟

Nginx 是一个高性能的 HTTP 和反向代理服务器。它以其高性能、稳定性、丰富的功能集、简单的配置和低资源消耗而闻名。本文介绍如何配置 Nginx 。

主要特点

  • 高性能: 采用事件驱动架构,能够处理大量并发连接
  • 低资源消耗: 内存占用少
  • 反向代理: 支持 HTTP、HTTPS、TCP 和 UDP 协议
  • 负载均衡: 支持多种负载均衡算法
  • 静态文件服务: 高效处理静态资源
  • 热部署: 支持不停机更新配置

Nginx 进程模型

Master-Worker 架构

Nginx 采用多进程模型,包含一个 Master 进程和多个 Worker 进程

┌─────────────────────────────────────┐
│     Master 进程 (主控进程)           │
│  - 读取配置文件                      │
│  - 管理 Worker 进程                  │
│  - 处理信号(reload/stop)           │
└──────────┬──────────────────────────┘
           │
    ┌──────┴──────┬──────┬──────┐
    ↓             ↓      ↓      ↓
┌────────┐  ┌────────┐  ┌────────┐
│Worker 1│  │Worker 2│  │Worker N│
│        │  │        │  │        │
│处理请求│  │处理请求│  │处理请求│
└────────┘  └────────┘  └────────┘

1. Master 进程(主进程)

职责

  • 读取和验证配置文件
  • 创建、管理和监控 Worker 进程
  • 接收外部信号(如 reload、stop、quit)
  • 不处理实际的网络请求

特点

  • 以 root 权限运行(需要绑定 80/443 端口)
  • 在整个生命周期中只有一个

2. Worker 进程(工作进程)

职责

  • 实际处理客户端请求
  • 接收来自 Master 分配的连接
  • 执行反向代理、负载均衡等操作
  • 处理静态文件、动态内容

特点

  • 以普通用户权限运行(由 user 指令指定)
  • 数量由 worker_processes 指令配置
  • 每个 Worker 独立运行,互不影响
  • 采用异步非阻塞的事件驱动模型

关键配置参数

worker_processes(Worker 进程数)

# 全局块配置
worker_processes auto;  # 自动检测 CPU 核心数
# worker_processes 4;   # 手动指定为 4 个 Worker

配置建议

  • 推荐值auto 或等于 CPU 核心数
  • 原因:每个 Worker 绑定一个 CPU 核心,避免进程切换开销
  • 查看 CPU 核心数grep processor /proc/cpuinfo | wc -l (Linux) 或 sysctl -n hw.ncpu (macOS)

示例

  • 4 核 CPU → worker_processes 4;
  • 8 核 CPU → worker_processes 8;

worker_connections(每个 Worker 的最大连接数)

events {
    worker_connections 1024;  # 每个 Worker 最多处理 1024 个连接
}

含义

  • 单个 Worker 进程能同时处理的最大连接数
  • 包括与客户端的连接和与后端服务器的连接

计算公式

理论最大并发连接数 = worker_processes × worker_connections

作为反向代理时的并发数 = (worker_processes × worker_connections) / 2
# 除以 2 是因为每个客户端请求需要 2 个连接:
# 1 个连接到 Nginx,1 个 Nginx 到后端服务器

完整示例与计算

# 4 核 CPU 服务器,预期支持 8000 并发连接

user nginx;
worker_processes 4;                # 4 个 Worker(匹配 CPU 核心数)
worker_rlimit_nofile 65535;        # 每个 Worker 最多打开 65535 个文件

events {
    worker_connections 4096;       # 每个 Worker 处理 4096 个连接
    use epoll;                     # Linux 使用 epoll(高性能)
    multi_accept on;               # 一次接受多个连接
}

# 计算结果:
# - 最大并发连接数 = 4 × 4096 = 16384(作为 Web 服务器)
# - 作为反向代理 = 16384 / 2 = 8192(满足 8000 并发需求)

基本配置结构

Nginx 配置文件采用块级结构(Block-based),由一系列指令(directives)和块(blocks)组成。配置文件通常位于 /etc/nginx/nginx.conf

1. 配置块(Context)

Nginx 配置由多个层级的配置块组成,每个块定义了一个配置上下文:

全局块(main)
├── events 块         # 事件模型配置
└── http 块           # HTTP 相关配置
    ├── upstream 块   # 负载均衡配置
    ├── server 块     # 虚拟主机配置
    │   └── location 块  # 请求路由配置
    └── server 块
        └── location 块

2. 各配置块的作用

配置块作用域主要配置内容
main(全局块)整个 Nginxworker 进程数、用户权限、错误日志、PID 文件
events所有网络连接连接数限制、事件驱动模型(epoll/kqueue)
http所有 HTTP 请求MIME 类型、日志格式、Gzip、超时时间
upstream后端服务器组负载均衡算法、服务器列表、健康检查
server单个虚拟主机监听端口、域名、SSL 证书
location特定 URL 路径代理规则、静态文件路径、重写规则

3. 指令继承与覆盖

  • 子块继承父块:子块会继承父块的配置
  • 子块可覆盖父块:子块中的相同指令会覆盖父块的配置
http {
    # 所有 server 都会继承这个配置
    client_max_body_size 10m;

    server {
        # 这个 server 覆盖了父块的配置
        client_max_body_size 50m;

        location /upload {
            # 这个 location 又覆盖了 server 的配置
            client_max_body_size 100m;
        }
    }
}

核心配置指令详解

1. 基础配置指令

监听与域名

上下文server

server {
    listen 80;                    # 监听端口
    listen 443 ssl http2;         # 监听 HTTPS 端口并启用 HTTP/2
    server_name example.com;      # 服务器域名
}
指令作用适用上下文示例
listen指定监听的端口和协议serverlisten 80;
listen 443 ssl;
server_name匹配请求的域名serverserver_name example.com www.example.com;

listen 参数说明

  • 80:HTTP 默认端口
  • 443 ssl:HTTPS 端口,启用 SSL
  • http2:启用 HTTP/2 协议(需要 SSL)
  • default_server:默认虚拟主机,匹配不到其他 server 时使用

文件路径

上下文http, server, location

http {
    root /var/www;           # HTTP 块设置默认根目录

    server {
        root /var/www/html;  # server 块可覆盖
        index index.html index.htm;

        location /app/ {
            root /data;      # location 块可再次覆盖
            # 或使用 alias
            alias /data/app/;
        }
    }
}
指令作用适用上下文示例
root设置资源根目录http, server, locationroot /var/www/html;
index目录访问时的默认文件http, server, locationindex index.html index.htm;
alias替换路径(仅 location)locationalias /data/;

root vs alias

  • root:拼接路径(root /var/www; + location /app//var/www/app/
  • alias:替换路径(alias /data/; + location /app//data/

2. Location 路径匹配

上下文server, location(location 可嵌套)

server {
    listen 80;

    location / { }                          # 前缀匹配
    location = /exact { }                   # 精确匹配
    location ^~ /static/ { }                # 优先前缀匹配
    location ~ \.php$ { }                   # 正则匹配(区分大小写)
    location ~* \.(jpg|png)$ { }            # 正则匹配(不区分大小写)

    # location 可以嵌套
    location /api/ {
        location /api/admin/ {
            # 嵌套 location
        }
    }
}
修饰符匹配方式优先级适用上下文示例
=精确匹配最高server, locationlocation = / { }
^~前缀匹配(不检查正则)server, locationlocation ^~ /static/ { }
~正则匹配(区分大小写)server, locationlocation ~ \.php$ { }
~*正则匹配(不区分大小写)server, locationlocation ~* \.(jpg|png)$ { }
普通前缀匹配server, locationlocation / { }

try_files

上下文server, location

server {
    try_files $uri $uri/ /index.html;  # server 级别

    location / {
        try_files $uri $uri/ /index.html;  # location 级别
        # 依次尝试:1. 文件 2. 目录 3. 返回 index.html
    }
}
指令作用适用上下文
try_files按顺序检查文件是否存在server, location

常用场景:SPA 应用的前端路由支持

3. 反向代理指令

所有 proxy_ 指令的上下文*:http, server, location

基础代理

上下文location(主要),server(少见)

http {
    server {
        location / {
            proxy_pass http://backend;              # 代理到后端服务器
        }

        location /api/ {
            proxy_pass http://localhost:3000;       # 代理到本地端口
            proxy_pass http://backend/api/;         # 代理并修改路径
        }
    }
}
指令作用适用上下文示例
proxy_pass转发请求到后端location, if in locationproxy_pass http://backend;

路径处理规则

  • proxy_pass http://backend; → 保留完整 URI
  • proxy_pass http://backend/; → 替换 location 路径

请求头设置

上下文http, server, location

http {
    # http 块:所有 server 继承
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;

    server {
        # server 块:所有 location 继承
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        location / {
            # location 块:仅此 location 生效
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}
指令作用适用上下文常用值
proxy_set_header设置转发到后端的请求头http, server, locationHost $host

常用请求头

  • Host:原始请求的域名
  • X-Real-IP:客户端真实 IP
  • X-Forwarded-For:完整的代理链 IP
  • X-Forwarded-Proto:原始协议(http/https)
  • Upgrade + Connection:WebSocket 支持

代理超时

上下文http, server, location

http {
    proxy_connect_timeout 60s;    # http 块:默认连接超时

    server {
        proxy_read_timeout 120s;  # server 块:覆盖为 120s

        location /api/ {
            proxy_connect_timeout 120s;  # location 块:长连接接口
            proxy_read_timeout 180s;     # 长耗时任务
            proxy_send_timeout 180s;     # 大文件上传
        }
    }
}
指令作用适用上下文默认值适用场景
proxy_connect_timeout与后端建立连接的超时http, server, location60s网络慢时增加
proxy_read_timeout从后端读取响应的超时http, server, location60s长耗时任务增加
proxy_send_timeout向后端发送请求的超时http, server, location60s大文件上传增加

错误重试

上下文http, server, location

http {
    # http 块:全局重试策略
    proxy_next_upstream error timeout http_502;
    proxy_next_upstream_tries 3;

    server {
        location /api/ {
            # location 块:特定接口覆盖
            proxy_next_upstream error timeout;
            proxy_next_upstream_tries 2;
        }
    }
}
指令作用适用上下文示例
proxy_next_upstream何时尝试下一个服务器http, server, locationerror timeout http_502
proxy_next_upstream_tries最大重试次数http, server, location3

proxy_next_upstream 参数

  • error:连接错误
  • timeout:超时
  • http_502/503/504:后端返回特定错误码
  • off:禁用重试

4. SSL/HTTPS 配置

所有 ssl_ 指令的上下文*:http, server(主要在 server 块使用)

证书配置

上下文http, server

http {
    # http 块:所有 HTTPS server 的默认证书
    # ssl_certificate /path/to/default.pem;
    # ssl_certificate_key /path/to/default.key;

    server {
        listen 443 ssl http2;

        # server 块:为此虚拟主机指定证书
        ssl_certificate /path/to/cert.pem;
        ssl_certificate_key /path/to/key.pem;
        ssl_dhparam /path/to/dhparam.pem;
    }
}
指令作用适用上下文必需
ssl_certificateSSL 证书文件路径http, server
ssl_certificate_keySSL 私钥文件路径http, server
ssl_dhparamDH 参数(增强安全性)http, server推荐

会话优化

上下文http, server

http {
    # http 块:所有 HTTPS server 共享会话缓存
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_session_tickets on;
}
指令作用适用上下文性能影响
ssl_session_cacheSSL 会话缓存http, server减少 1-2 RTT
ssl_session_timeout会话有效期http, server10m 为佳
ssl_session_tickets无状态会话恢复http, server减少服务器内存

5. 缓存控制

上下文

  • expires: http, server, location
  • add_header: http, server, location
http {
    expires 7d;  # http 块:默认缓存 7 天

    server {
        location / {
            expires -1;  # 首页不缓存
        }

        location ~* \.(js|css)$ {
            expires 1y;  # 静态资源缓存 1 年
            add_header Cache-Control "public, immutable";
        }
    }
}
指令作用适用上下文示例
expires设置过期时间http, server, location30d, 1y, -1
add_header添加响应头http, server, locationCache-Control "no-store"

Cache-Control 常用值

  • public:允许 CDN 和代理缓存
  • private:仅浏览器缓存
  • no-store:完全不缓存
  • no-cache:每次验证缓存
  • immutable:文件永不改变(适合带哈希的文件)

6. 负载均衡指令

upstream backend {
    least_conn;                             # 负载均衡算法
    server backend1.com:8080 weight=3;      # 后端服务器 + 权重
    server backend2.com:8080 weight=2;
    server backend3.com:8080 backup;        # 备用服务器
}

upstream 块指令

指令作用示例
server定义后端服务器server 192.168.1.10:8080;
weight服务器权重weight=3
backup备用服务器标记backup
max_fails失败次数阈值max_fails=3
fail_timeout失败超时时间fail_timeout=30s

负载均衡算法

算法指令特点
轮询默认依次分配
最少连接least_conn;分配给连接数最少的服务器
IP 哈希ip_hash;同一 IP 始终访问同一服务器
随机random;随机选择服务器

7. Gzip 压缩

上下文http, server, location

http {
    # http 块:全局启用 gzip
    gzip on;
    gzip_vary on;
    gzip_min_length 1k;
    gzip_comp_level 6;
    gzip_buffers 32 4k;
    gzip_types text/plain text/css application/javascript;
    gzip_disable "MSIE [1-6]\.";

    server {
        # server 块可覆盖
        gzip_comp_level 9;  # 此 server 使用更高压缩级别
    }
}
指令作用适用上下文推荐值
gzip启用 gzip 压缩http, server, locationon
gzip_min_length最小压缩大小http, server, location1k
gzip_comp_level压缩级别http, server, location6(1-9,越高越慢)
gzip_types要压缩的文件类型http, server, locationtext/* application/javascript ...
gzip_disable禁用 gzip 的条件http, server, location"MSIE [1-6]\."

8. URL 重写

上下文

  • return: server, location, if
  • rewrite: server, location, if
server {
    # server 块:重定向所有 HTTP 到 HTTPS
    return 301 https://$server_name$request_uri;

    location /old/ {
        # location 块:URL 重写
        rewrite ^/old(.*)$ /new$1 permanent;
    }
}
指令作用适用上下文状态码
return立即返回响应server, location, if301, 302, 200
rewriteURL 重写server, location, ifpermanent(301), redirect(302)

rewrite 标志

  • permanent:301 永久重定向
  • redirect:302 临时重定向
  • break:停止当前规则,不再匹配
  • last:停止当前规则,重新搜索 location

9. 限流限速

上下文

  • limit_req_zone: http
  • limit_req: http, server, location
http {
    # http 块:定义限流区域(必须在 http 块)
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

    server {
        location /api/ {
            # location 块:应用限流
            limit_req zone=api_limit burst=20 nodelay;
        }
    }
}
指令作用适用上下文示例
limit_req_zone定义限流区域httpzone=api_limit:10m rate=10r/s
limit_req应用限流http, server, locationzone=api_limit burst=20

参数说明

  • zone=name:size:共享内存区域名和大小
  • rate=10r/s:每秒 10 个请求
  • burst=20:允许突发 20 个请求
  • nodelay:不延迟处理突发请求

10. 常用变量

Nginx 提供了大量内置变量,用于配置中的动态取值:

变量含义示例值
$host请求的主机名example.com
$server_nameserver 块定义的域名example.com
$uri当前请求的 URI/path/to/file.html
$request_uri完整的原始 URI(含参数)/path?id=123
$scheme协议httphttps
$remote_addr客户端 IP192.168.1.100
$proxy_add_x_forwarded_for追加 X-Forwarded-For客户端IP, 代理IP
$http_upgradeUpgrade 请求头的值websocket
$http_user_agentUser-Agent 请求头Mozilla/5.0 ...

实战配置案例

1. HTTP 与 HTTPS 共存配置

场景:同时监听 80 和 443 端口,在同一个 server 块中处理。

server {
    listen 80;
    listen 443 ssl http2;
    server_name example.com;
    charset utf-8;

    # SSL 证书配置
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    ssl_dhparam /path/to/dhparam.pem;

    # 应用配置...
}

优点:减少配置重复,HTTP 和 HTTPS 共享同一套 location 规则。

2. 微服务路由配置

场景:将不同路径的请求路由到不同的后端微服务。

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

    # API 服务
    location /api/ {
        client_max_body_size 100m;
        proxy_connect_timeout 120s;

        proxy_set_header X-Origin-Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host api-service.internal;

        proxy_next_upstream off;
        proxy_next_upstream_tries 3;
        proxy_pass http://api_backend;
    }

    # 管理后台服务
    location /admin/ {
        client_max_body_size 200m;
        proxy_connect_timeout 180s;
        proxy_read_timeout 180s;

        proxy_set_header X-Origin-Host $host;
        proxy_set_header Host admin-service.internal;
        proxy_pass http://admin_backend;
    }
}

关键点

  • 不同服务配置不同的超时和请求体大小
  • 使用 X-Origin-Host 保留原始域名
  • 覆盖 Host 头用于内部服务路由

3. SPA + OSS 静态资源

场景:前端应用 托管在 OSS,通过 Nginx 代理访问。

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

    # 主应用(从 OSS 代理)
    location / {
        add_header Cache-Control "no-store";
        add_header X-Frame-Options "SAMEORIGIN" always;

        proxy_intercept_errors on;
        error_page 404 =200 /index.html;

        proxy_pass https://cdn.example.com/app/web-static/production/;
    }

    # 特定版本的应用(支持 commit/review 分支预览)
    location ~ /(commit|review)/(.*)/app/(.*) {
        add_header Cache-Control "no-store";
        add_header X-Frame-Options "SAMEORIGIN" always;

        # URL 重写
        rewrite ^/(commit|review)/(.*)/app/(.*) /app/web-static/$1/$2/index.html break;
        proxy_pass https://cdn.example.com;
    }
}

技巧

  • error_page 404 =200 /index.html:将 404 转为 200,支持前端路由
  • 在 location 块内启用 gzip,针对特定路径优化
  • 使用正则捕获组实现灵活的 URL 重写

4. WebSocket 长连接支持

场景:支持 WebSocket 实时通信。

location /ws/ {
    proxy_pass http://websocket_backend;

    # WebSocket 必需配置
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    # 超长超时时间(1 小时)
    proxy_read_timeout 3600s;
}

关键点

  • 必须设置 proxy_http_version 1.1
  • 必须设置 UpgradeConnection
  • 设置足够长的 proxy_read_timeout