最后更新于:2026年7月

Nginx 反向代理指南
Nginx:高性能 Web 服务器与反向代理

Nginx 是互联网的基石。 根据 W3Techs 2026 年统计,Nginx 服务着全球 34% 的网站,是使用率最高的 Web 服务器。从个人博客到 Netflix、淘宝这样的超大规模应用,Nginx 都在默默支撑。

但很多人对 Nginx 的使用还停留在「配个 server 块跑个静态网站」的阶段。Nginx 真正的威力在于反向代理、负载均衡、缓存、限流、SSL 终端等高级功能。

本文从核心原理到生产级配置,带你全面掌握 Nginx。


一、Nginx 核心概念

1.1 什么是 Nginx?

Nginx 是一个高性能的 HTTP 和反向代理 Web 服务器,同时提供 IMAP/POP3/SMTP 代理服务。

核心特点:

特性说明
高并发单机可处理数万并发连接
低内存10000个非活跃连接仅消耗约 2.5MB 内存
事件驱动异步非阻塞,不同于 Apache 的线程模型
热部署修改配置后无需重启即可生效
模块化丰富的模块生态,功能可扩展
反向代理专业级反向代理和负载均衡

1.2 正向代理 vs 反向代理

PLAINTEXT
正向代理(代理客户端):
客户端 → [正向代理] → 服务器
例:VPN、翻墙代理
客户端知道要访问谁,代理帮你去访问

反向代理(代理服务端):
客户端 → [反向代理] → 服务器1/服务器2/服务器3
例:Nginx 负载均衡器
客户端不知道真正提供服务的是谁,以为代理就是服务器

反向代理的核心价值:

1.3 Nginx 架构

PLAINTEXT
Nginx 架构:

Master Process(主进程)
  ├── Worker Process 1  ← 处理请求
  ├── Worker Process 2  ← 处理请求
  ├── Worker Process 3  ← 处理请求
  └── Cache Manager     ← 管理缓存

每个 Worker 使用 epoll/kqueue 事件驱动
一个 Worker 可以处理数千个并发连接

为什么 Nginx 这么快?

  1. 事件驱动:一个 Worker 进程可以同时处理数千个连接
  2. 异步非阻塞:不会因为一个慢请求阻塞其他请求
  3. 零拷贝技术sendfile 系统调用,数据直接从磁盘到网络
  4. 内存池:减少内存分配和释放的开销
  5. 多进程模型:Worker 之间独立,互不影响

二、安装 Nginx

2.1 各平台安装

Ubuntu/Debian:

BASH
# 安装稳定版
sudo apt update
sudo apt install nginx

# 或安装最新主线版
sudo apt install curl gnupg2 ca-certificates lsb-release debian-archive-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/mainline/ubuntu $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
sudo apt update
sudo apt install nginx

CentOS/RHEL:

BASH
sudo yum install epel-release
sudo yum install nginx

macOS:

BASH
brew install nginx

Docker:

BASH
docker run -d --name nginx -p 80:80 -p 443:443 nginx:latest

2.2 验证安装

BASH
# 查看版本
nginx -v
# nginx version: nginx/1.27.0

# 查看编译参数
nginx -V

# 测试配置文件
nginx -t

# 重新加载配置
nginx -s reload

# 启动/停止
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
sudo systemctl status nginx

2.3 目录结构

PLAINTEXT
/etc/nginx/
├── nginx.conf          # 主配置文件
├── conf.d/             # 自定义配置(推荐)
│   ├── default.conf
│   ├── site1.conf
│   └── site2.conf
├── sites-available/    # 可用站点(Debian 系)
├── sites-enabled/      # 已启用站点(Debian 系)
├── mime.types          # MIME 类型
├── fastcgi_params      # FastCGI 参数
├── proxy_params         # 代理参数
└── snippets/           # 可复用的配置片段

/var/log/nginx/
├── access.log          # 访问日志
└── error.log           # 错误日志

/usr/share/nginx/html/  # 默认网站根目录
/var/www/html/          # Debian 系默认根目录

三、配置文件结构

3.1 主配置文件

NGINX
# /etc/nginx/nginx.conf

# ===== 全局块 =====
user www-data;
worker_processes auto;           # 自动设置(等于 CPU 核心数)
worker_rlimit_nofile 65535;      # 最大文件描述符
pid /run/nginx.pid;

# ===== 事件块 =====
events {
    worker_connections 10240;    # 每个 Worker 最大连接数
    use epoll;                   # 事件模型(Linux 推荐 epoll)
    multi_accept on;             # 一次接受所有连接
}

# ===== HTTP 块 =====
http {
    # 基础设置
    sendfile on;                 # 零拷贝
    tcp_nopush on;               # 数据包累积后发送
    tcp_nodelay on;              # 禁用 Nagle 算法
    keepalive_timeout 65;        # 长连接超时
    keepalive_requests 1000;     # 长连接最大请求数
    types_hash_max_size 2048;
    server_tokens off;           # 隐藏 Nginx 版本号
    
    # MIME 类型
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    
    # 日志格式
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    '$request_time $upstream_response_time';
    
    access_log /var/log/nginx/access.log main;
    error_log /var/log/nginx/error.log warn;
    
    # Gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml application/json 
               application/javascript application/xml application/xml+rss 
               application/atom+xml image/svg+xml;
    
    # 包含其他配置
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

3.2 配置优先级

PLAINTEXT
Nginx 配置层级:

http {
    # 对所有 server 生效
    server {
        # 对该 server 内所有 location 生效
        listen 80;
        server_name example.com;
        
        location / {
            # 对匹配的请求生效
        }
        
        location /api {
            # 更具体的匹配
        }
    }
}

location 匹配优先级:

PLAINTEXT
1. =    精确匹配(最高优先级)
   location = /favicon.ico { ... }

2. ^~   前缀匹配(不再正则)
   location ^~ /static/ { ... }

3. ~ / ~*  正则匹配(区分/不区分大小写)
   location ~* \.(jpg|png|gif)$ { ... }

4. 无前缀  普通前缀匹配(最长匹配)
   location /api { ... }

四、静态网站配置

4.1 基础静态网站

NGINX
# /etc/nginx/conf.d/mysite.conf

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/mysite;
    index index.html;
    
    # 静态文件
    location / {
        try_files $uri $uri/ =404;
    }
    
    # 静态资源缓存
    location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
    
    # 安全:禁止访问隐藏文件
    location ~ /\. {
        deny all;
    }
    
    # 错误页面
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
}

4.2 Vue/React SPA 配置

NGINX
server {
    listen 80;
    server_name myapp.com;
    root /var/www/myapp/dist;
    index index.html;
    
    # SPA 路由支持(所有路由都指向 index.html)
    location / {
        try_files $uri $uri/ /index.html;
    }
    
    # 静态资源长期缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    # index.html 不缓存
    location = /index.html {
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }
    
    # gzip 压缩
    gzip on;
    gzip_types text/plain text/css application/javascript application/json image/svg+xml;
    gzip_min_length 1024;
}

五、反向代理配置

5.1 基础反向代理

NGINX
server {
    listen 80;
    server_name api.example.com;
    
    location / {
        proxy_pass http://localhost:3000;
        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.2 完整反向代理配置

NGINX
server {
    listen 80;
    server_name api.example.com;
    
    # 代理缓冲设置
    proxy_buffering on;
    proxy_buffer_size 4k;
    proxy_buffers 8 4k;
    proxy_busy_buffers_size 8k;
    
    # 超时设置
    proxy_connect_timeout 5s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;
    
    # 代理到后端服务
    location /api/ {
        proxy_pass http://localhost:3000/;
        
        # 传递请求头
        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 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        
        # 超时
        proxy_read_timeout 86400s;  # WebSocket 长连接
    }
    
    # 代理到不同端口
    location /api/users/ {
        proxy_pass http://localhost:3001/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    
    location /api/orders/ {
        proxy_pass http://localhost:3002/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

5.3 proxy_pass 路径规则

NGINX
# 规则1:带斜杠 → 替换匹配路径
location /api/ {
    proxy_pass http://backend/;
}
# 请求 /api/users → 后端收到 /users

# 规则2:不带斜杠 → 保留完整路径
location /api/ {
    proxy_pass http://backend;
}
# 请求 /api/users → 后端收到 /api/users

# 规则3:带路径 → 替换匹配路径
location /api/ {
    proxy_pass http://backend/v2/;
}
# 请求 /api/users → 后端收到 /v2/users

# 规则4:使用变量
location /api/ {
    proxy_pass http://backend$request_uri;
}
# 请求 /api/users  后端收到 /api/users

六、负载均衡

6.1 负载均衡配置

NGINX
# 定义上游服务器池
upstream backend {
    server 192.168.1.10:3000;
    server 192.168.1.11:3000;
    server 192.168.1.12:3000;
}

server {
    listen 80;
    server_name api.example.com;
    
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

6.2 负载均衡策略

策略1:轮询(默认)

NGINX
upstream backend {
    server 192.168.1.10:3000;
    server 192.168.1.11:3000;
    server 192.168.1.12:3000;
}
# 请求按顺序轮流分配

策略2:权重(weight)

NGINX
upstream backend {
    server 192.168.1.10:3000 weight=3;  # 30% 请求
    server 192.168.1.11:3000 weight=2;  # 20% 请求
    server 192.168.1.12:3000 weight=5;  # 50% 请求
}
# 按权重比例分配(服务器性能不同时使用)

策略3:IP 哈希(ip_hash)

NGINX
upstream backend {
    ip_hash;  # 同一 IP 总是访问同一台服务器
    server 192.168.1.10:3000;
    server 192.168.1.11:3000;
    server 192.168.1.12:3000;
}
# 保持会话粘性(Session 粘滞)
# 同一用户的请求总是到同一台服务器

策略4:最少连接(least_conn)

NGINX
upstream backend {
    least_conn;  # 分配给连接数最少的服务器
    server 192.168.1.10:3000;
    server 192.168.1.11:3000;
    server 192.168.1.12:3000;
}
# 适合请求处理时间差异较大的场景

策略5:一致性哈希(第三方模块)

NGINX
upstream backend {
    hash $request_uri consistent;  # 按 URI 一致性哈希
    server 192.168.1.10:3000;
    server 192.168.1.11:3000;
    server 192.168.1.12:3000;
}
# 适合缓存场景,同一 URL 总是到同一服务器

6.3 健康检查

被动健康检查(内置):

NGINX
upstream backend {
    server 192.168.1.10:3000 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:3000 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:3000 max_fails=3 fail_timeout=30s;
    
    # max_fails=3     失败3次后标记为不可用
    # fail_timeout=30s  不可用状态持续30秒
}

# 备用服务器
upstream backend {
    server 192.168.1.10:3000;
    server 192.168.1.11:3000;
    server 192.168.1.12:3000 backup;  # 仅当其他都不可用时启用
}

主动健康检查(Nginx Plus / nginx_upstream_check_module):

NGINX
# Nginx Plus 商业版
upstream backend {
    server 192.168.1.10:3000;
    server 192.168.1.11:3000;
    
    health_check interval=5s uri=/health matches=2;
}

match health {
    status 200;
    header Content-Type = application/json;
    body ~ '"status":"ok"';
}

6.4 慢启动

NGINX
upstream backend {
    server 192.168.1.10:3000 slow_start=30s;
    server 192.168.1.11:3000 slow_start=30s;
}
# 新加入的服务器逐渐增加流量,避免突然涌入大量请求

七、SSL/TLS 与 HTTPS

7.1 使用 Let’s Encrypt 免费证书

BASH
# 安装 Certbot
sudo apt install certbot python3-certbot-nginx

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

# 自动续期(Certbot 会自动设置 cron)
sudo certbot renew --dry-run  # 测试续期

7.2 HTTPS 配置

NGINX
# HTTP 跳转 HTTPS
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

# HTTPS 服务器
server {
    listen 443 ssl http2;
    server_name example.com www.example.com;
    
    # SSL 证书
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # SSL 优化
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;
    
    # 现代协议
    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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    
    # HSTS(强制浏览器使用 HTTPS)
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
    
    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;
    
    # 网站配置
    root /var/www/mysite;
    index index.html;
    
    location / {
        try_files $uri $uri/ =404;
    }
}

7.3 SSL 安全评级配置

NGINX
# 达到 SSL Labs A+ 评级的配置

server {
    listen 443 ssl http2;
    server_name example.com;
    
    # 证书
    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;
    
    # 仅 TLS 1.2 和 1.3
    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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
    ssl_prefer_server_ciphers on;
    
    # 会话缓存
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;
    
    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    
    # 安全头
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
    add_header X-Frame-Options DENY 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 Content-Security-Policy "default-src 'self'; https://*" always;
}

7.4 反向代理 SSL 终端

NGINX
# Nginx 作为 SSL 终端,后端使用 HTTP

server {
    listen 443 ssl http2;
    server_name api.example.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    
    location / {
        proxy_pass http://backend;
        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 https;  # 告诉后端是 HTTPS
    }
}

八、缓存配置

8.1 代理缓存

NGINX
# http 块中定义缓存区域
http {
    # 缓存路径和参数
    proxy_cache_path /var/cache/nginx 
                     levels=1:2 
                     keys_zone=api_cache:10m 
                     max_size=1g 
                     inactive=60m 
                     use_temp_path=off;
}

server {
    listen 80;
    server_name api.example.com;
    
    location /api/ {
        proxy_pass http://backend;
        
        # 启用缓存
        proxy_cache api_cache;
        proxy_cache_valid 200 10m;    # 200 响应缓存 10 分钟
        proxy_cache_valid 404 1m;     # 404 缓存 1 分钟
        proxy_cache_valid 500 0s;     # 500 不缓存
        
        # 缓存 key
        proxy_cache_key "$scheme$request_method$host$request_uri";
        
        # 添加缓存状态头
        add_header X-Cache-Status $upstream_cache_status;
        # MISS: 未命中缓存
        # HIT: 命中缓存
        # EXPIRED: 缓存过期
        # STALE: 使用过期缓存(后端不可用时)
        
        # 绕过缓存的条件
        proxy_cache_bypass $http_authorization $cookie_nocache $arg_nocache;
        proxy_no_cache $http_authorization $cookie_nocache $arg_nocache;
        
        # 后端不可用时使用过期缓存
        proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
        
        # 锁定(防止缓存击穿)
        proxy_cache_lock on;
        proxy_cache_lock_timeout 5s;
    }
}

8.2 浏览器缓存

NGINX
server {
    listen 80;
    
    # HTML 不缓存
    location ~ \.html$ {
        add_header Cache-Control "no-cache, no-store, must-revalidate";
        add_header Pragma "no-cache";
        expires -1;
    }
    
    # CSS/JS 长期缓存
    location ~* \.(css|js)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    # 图片长期缓存
    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp|avif)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
    
    # 字体长期缓存
    location ~* \.(woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        add_header Access-Control-Allow-Origin *;
    }
}

九、限流与安全防护

9.1 请求限流

NGINX
# http 块中定义限流区域
http {
    # 按 IP 限流:每秒 10 个请求
    limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
    
    # 按连接数限流:每个 IP 最多 20 个并发连接
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
}

server {
    listen 80;
    
    # 应用限流
    location /api/ {
        limit_req zone=req_limit burst=20 nodelay;
        # burst=20   突发请求排队 20 个
        # nodelay    不延迟,立即处理
        
        limit_conn conn_limit 20;
        # 每个 IP 最多 20 个并发连接
        
        proxy_pass http://backend;
    }
    
    # 登录接口更严格
    location /api/login {
        limit_req zone=req_limit burst=5 nodelay;
        limit_conn conn_limit 5;
        proxy_pass http://backend;
    }
    
    # 限流时返回 429
    limit_req_status 429;
    limit_conn_status 429;
}

9.2 访问控制

NGINX
server {
    listen 80;
    
    # IP 白名单
    location /admin/ {
        allow 192.168.1.0/24;     # 内网
        allow 10.0.0.0/8;         # VPN
        deny all;                 # 其他拒绝
        
        proxy_pass http://backend;
    }
    
    # 按地理位置限制(需要 GeoIP 模块)
    location / {
        # if ($geoip_country_code != "CN") {
        #     return 403;
        # }
        proxy_pass http://backend;
    }
    
    # 防止恶意 User-Agent
    if ($http_user_agent ~* (bot|crawl|spider|scrape)) {
        return 403;
    }
    
    # 防止热链
    location ~* \.(jpg|jpeg|png|gif)$ {
        valid_referers none blocked mysite.com *.mysite.com;
        if ($invalid_referer) {
            return 403;
        }
    }
    
    # 禁止访问敏感文件
    location ~ /\.(git|env|htaccess) {
        deny all;
        return 404;
    }
    
    location ~* \.(sql|bak|log|ini|sh)$ {
        deny all;
        return 404;
    }
}

9.3 DDoS 防护

NGINX
http {
    # 限制请求体大小
    client_max_body_size 10m;
    
    # 限制请求头大小
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;
    
    # 超时设置(减少慢攻击影响)
    client_body_timeout 10s;
    client_header_timeout 10s;
    keepalive_timeout 15s;
    send_timeout 10s;
    
    # 限流区域
    limit_req_zone $binary_remote_addr zone=ddos:10m rate=30r/s;
}

server {
    listen 80;
    
    # 全局限流
    limit_req zone=ddos burst=50 nodelay;
    
    # 限制连接数
    limit_conn addr 10;
    
    location / {
        proxy_pass http://backend;
    }
}

十、WebSocket 代理

NGINX
# HTTP 升级到 WebSocket
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name ws.example.com;
    
    location /ws {
        proxy_pass http://localhost:3000;
        
        # WebSocket 必需的头
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        
        # 通用代理头
        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 长连接超时
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
        
        # 禁用缓冲
        proxy_buffering off;
    }
}

十一、日志与分析

11.1 自定义日志格式

NGINX
http {
    # 详细日志格式
    log_format detailed '$remote_addr - $remote_user [$time_local] '
                        '"$request" $status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent" '
                        'rt=$request_time uct=$upstream_connect_time '
                        'uht=$upstream_header_time urt=$upstream_response_time '
                        'cache=$upstream_cache_status';
    
    # JSON 格式日志(方便 ELK 采集)
    log_format json_combined escape=json
        '{'
            '"time":"$time_iso8601",'
            '"remote_addr":"$remote_addr",'
            '"request":"$request",'
            '"status":$status,'
            '"body_bytes_sent":$body_bytes_sent,'
            '"request_time":$request_time,'
            '"upstream_response_time":"$upstream_response_time",'
            '"referer":"$http_referer",'
            '"user_agent":"$http_user_agent"'
        '}';
    
    access_log /var/log/nginx/access.log detailed;
    # 或 JSON 格式
    # access_log /var/log/nginx/access.log json_combined;
}

11.2 日志轮转

BASH
# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 640 www-data adm
    sharedscripts
    postrotate
        if [ -f /var/run/nginx.pid ]; then
            kill -USR1 $(cat /var/run/nginx.pid)
        fi
    endscript
}

11.3 日志分析

BASH
# Top 10 访问 IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10

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

# 最受欢迎的页面
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# 请求时间最长的 10 个请求
awk '{print $NF, $7}' /var/log/nginx/access.log | sort -rn | head -10

# 4xx/5xx 错误统计
awk '$9 ~ /^4|^5/ {print $9, $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

# 每小时请求量
awk '{print $4}' /var/log/nginx/access.log | cut -c14-15 | sort | uniq -c

# 流量统计
awk '{sum+=$10} END {printf "总流量: %.2f GB\n", sum/1024/1024/1024}' /var/log/nginx/access.log

十二、性能调优

12.1 系统级优化

BASH
# /etc/sysctl.conf

# 增加最大文件描述符
fs.file-max = 1000000

# TCP 优化
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 65535

# TCP 快速回收
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1

# TCP KeepAlive
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl = 30

# 端口范围
net.ipv4.ip_local_port_range = 10000 65535

# 应用配置
sysctl -p
BASH
# /etc/security/limits.conf

# Nginx 用户文件描述符限制
www-data soft nofile 65535
www-data hard nofile 65535

12.2 Nginx 配置优化

NGINX
# /etc/nginx/nginx.conf

user www-data;
worker_processes auto;
worker_rlimit_nofile 100000;

events {
    worker_connections 16384;
    use epoll;
    multi_accept on;
}

http {
    # 基础优化
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    
    # 长连接
    keepalive_timeout 30s;
    keepalive_requests 1000;
    
    # 后端长连接
    upstream backend {
        server 127.0.0.1:3000;
        keepalive 32;  # 保持 32 个长连接到后端
    }
    
    # 缓冲优化
    client_body_buffer_size 16k;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;
    
    # 文件缓存(open_file_cache)
    open_file_cache max=10000 inactive=60s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;
    
    # Gzip
    gzip on;
    gzip_comp_level 5;
    gzip_min_length 1024;
    gzip_types text/plain text/css application/javascript application/json 
               application/xml text/xml application/xml+rss image/svg+xml;
    gzip_vary on;
    gzip_proxied any;
    
    # Brotli(需要模块)
    # brotli on;
    # brotli_comp_level 6;
    # brotli_types text/plain text/css application/javascript application/json;
}

12.3 性能检查

BASH
# 查看 Nginx 连接状态
ss -s

# 查看当前连接数
nginx -V 2>&1 | grep -o with-http_stub_status_module
# 如果有 stub_status 模块,可以开启状态页面

# 配置状态页面
# nginx.conf
# server {
#     listen 127.0.0.1:8080;
#     location /nginx_status {
#         stub_status on;
#         access_log off;
#         allow 127.0.0.1;
#         deny all;
#     }
# }

# 查看状态
curl http://127.0.0.1:8080/nginx_status
# Active connections: 15
# server accepts handled requests
#  8456 8456 32891
#  Reading: 0 Writing: 1 Waiting: 14

# 压力测试
ab -n 10000 -c 100 http://example.com/
wrk -t12 -c400 -d30s http://example.com/

十三、高可用方案

13.1 Keepalived + Nginx

PLAINTEXT
                    VIP: 192.168.1.100
                    /                \
            Nginx Master          Nginx Backup
            192.168.1.101         192.168.1.102
                |                      |
            后端服务器群           后端服务器群
            192.168.1.10~12       192.168.1.10~12

Master 配置:

BASH
# /etc/keepalived/keepalived.conf

vrrp_script chk_nginx {
    script "pidof nginx"
    interval 2
    weight 2
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    
    authentication {
        auth_type PASS
        auth_pass mypassword
    }
    
    virtual_ipaddress {
        192.168.1.100/24
    }
    
    track_script {
        chk_nginx
    }
}

Backup 配置:

BASH
vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 90          # 比 Master 低
    advert_int 1
    
    authentication {
        auth_type PASS
        auth_pass mypassword
    }
    
    virtual_ipaddress {
        192.168.1.100/24
    }
    
    track_script {
        chk_nginx
    }
}

13.2 零停机部署

BASH
#!/usr/bin/env bash
# zero_downtime_deploy.sh

set -euo pipefail

# Nginx 平滑升级 / 后端零停机部署

# 方法1:Nginx 平滑升级
echo "1. 备份旧 Nginx"
cp /usr/sbin/nginx /usr/sbin/nginx.old

echo "2. 替换新 Nginx"
cp /path/to/new/nginx /usr/sbin/nginx

echo "3. 发送 USR2 信号(启动新 Master)"
kill -USR2 $(cat /var/run/nginx.pid)

echo "4. 发送 WINCH 信号(旧 Master 优雅停止 Worker)"
kill -WINCH $(cat /var/run/nginx.pid.oldbin)

echo "5. 确认新 Master 正常后,退出旧 Master"
kill -QUIT $(cat /var/run/nginx.pid.oldbin)

# 方法2:后端零停机部署(利用负载均衡)
# 1. 从负载均衡移除一台后端
# 2. 部署新版本到该后端
# 3. 健康检查通过后加回
# 4. 逐台重复

# Nginx 配置 API 动态修改(需要 Nginx Plus)
# 或使用 consul-template + nginx

十四、Docker + Nginx 部署

14.1 Dockerfile

DOCKERFILE
# Dockerfile
FROM node:20-alpine as builder
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile
COPY . .
RUN pnpm build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

14.2 docker-compose.yml

YAML
# docker-compose.yml
version: '3.8'

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - ./ssl:/etc/nginx/ssl
      - ./html:/usr/share/nginx/html
      - nginx-cache:/var/cache/nginx
    depends_on:
      - app
    restart: always
    networks:
      - frontend

  app:
    build: ./app
    expose:
      - "3000"
    environment:
      - NODE_ENV=production
    deploy:
      replicas: 3
    restart: always
    networks:
      - frontend

volumes:
  nginx-cache:

networks:
  frontend:

14.3 Nginx 配置(Docker 版)

NGINX
# nginx.conf

upstream app {
    # Docker 服务名作为主机名
    app:3000;
    
    # 如果有多个副本
    # app:3000 weight=1;
    # app:3000 weight=1;
    # app:3000 weight=1;
}

server {
    listen 80;
    server_name _;
    
    # 健康检查端点
    location /health {
        return 200 'ok';
        add_header Content-Type text/plain;
    }
    
    location / {
        proxy_pass http://app;
        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;
    }
}

十五、常见问题

Q1:502 Bad Gateway 怎么办?

PLAINTEXT
原因:Nginx 无法连接到后端服务

排查步骤:
1. 检查后端服务是否运行
   systemctl status myapp
   curl http://localhost:3000/health

2. 检查 Nginx 错误日志
   tail -f /var/log/nginx/error.log

3. 检查防火墙/安全组
   iptables -L -n

4. 检查 SELinux
   getenforce  # 如果是 Enforcing,可能阻止了代理
   setsebool -P httpd_can_network_connect 1

Q2:504 Gateway Timeout 怎么办?

NGINX
# 增加超时时间
location /api/ {
    proxy_pass http://backend;
    proxy_connect_timeout 60s;
    proxy_send_timeout 120s;
    proxy_read_timeout 120s;
}

Q3:文件上传 413 错误?

NGINX
# 增加上传文件大小限制
http {
    client_max_body_size 50m;  # 全局设置
}

server {
    location /upload {
        client_max_body_size 100m;  # 特定路径设置
        proxy_pass http://backend;
    }
}

Q4:配置不生效怎么办?

BASH
# 1. 检查配置语法
nginx -t

# 2. 重新加载
nginx -s reload

# 3. 检查是否真正重启
systemctl status nginx

# 4. 检查端口监听
ss -tlnp | grep nginx

# 5. 清除浏览器缓存或用 curl 测试
curl -I http://example.com/

Q5:Nginx 性能怎么优化?

PLAINTEXT
1. 调整 worker_processes 和 worker_connections
2. 开启 sendfile、tcp_nopush、tcp_nodelay
3. 开启 gzip 压缩
4. 配置缓存(proxy_cache 和浏览器缓存)
5. 使用 HTTP/2
6. 开启 keepalive 长连接
7. 优化 SSL/TLS 配置
8. 使用 open_file_cache
9. 调整系统参数(sysctl)
10. 监控和分析日志

十六、总结

Nginx 配置检查清单

Nginx 学习路径

PLAINTEXT
入门(第1周):
  → 安装 Nginx
  → 配置静态网站
  → 理解配置文件结构

进阶(第2-3周):
  → 反向代理配置
  → 负载均衡
  → SSL/HTTPS 配置
  → 日志分析

高级(第1-2月):
  → 缓存配置
  → 限流和安全防护
  → WebSocket 代理
  → 性能调优

专家(第3月+):
  → 高可用(Keepalived)
  → 零停机部署
  → 动态配置
  → Lua 扩展(OpenResty)


Nginx 是运维工程师和后端开发者的必修课。 掌握 Nginx,你就掌握了高性能 Web 服务的钥匙。从静态文件服务到大规模负载均衡,Nginx 都能优雅地胜任。🚀

版权声明

作者: 易邦

链接: https://blog.e8k.net/posts/nginx-reverse-proxy-guide-2026/

许可证: 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。