Skip to content

Nginx 详解:高性能反向代理与负载均衡

Nginx 是业界最主流的高性能 HTTP 服务器、反向代理和负载均衡器。在微服务架构中,Nginx 通常作为统一入口网关,负责流量分发、SSL 卸载、静态资源加速和请求限流。

一、为什么需要 Nginx?

1.1 Nginx 解决了什么问题?

在微服务架构中,前端需要调用多个后端服务,直接暴露每个服务会产生一系列问题:

没有 Nginx 时:
浏览器 → order-service:8080/api/orders
浏览器 → inventory-service:8081/api/inventory
浏览器 → user-service:8082/api/users
问题:跨域、多端口暴露、SSL 证书多份、无统一限流

有了 Nginx 后:
浏览器 → Nginx:443/api/orders    → order-service:8080
浏览器 → Nginx:443/api/inventory → inventory-service:8081
浏览器 → Nginx:443/api/users     → user-service:8082
好处:统一入口、统一 SSL、跨域解决、统一限流、静态资源缓存

1.2 Nginx 的核心能力

能力说明典型场景
反向代理客户端请求 → Nginx → 后端服务,隐藏后端真实 IP统一入口,屏蔽后端结构
负载均衡将请求分发到多个后端实例水平扩展,高可用
静态资源服务直接返回 HTML/CSS/JS/图片,不经过后端前后端分离,降低后端压力
SSL/TLS 终止在 Nginx 层处理 HTTPS,后端用 HTTP简化证书管理
缓存缓存后端响应,减少重复请求加速读取,降低后端压力
限流控制请求频率,防止恶意攻击防刷、防 DDoS
动静分离静态资源由 Nginx 直接返回,动态请求转发后端性能优化
WebSocket 代理支持 WebSocket 协议的长连接代理实时推送

二、核心架构

2.1 Master-Worker 进程模型

                    ┌──────────┐
                    │  Master  │  ← 读取配置、管理 Worker
                    └────┬─────┘
          ┌──────────────┼──────────────┐
          ▼              ▼              ▼
    ┌──────────┐  ┌──────────┐  ┌──────────┐
    │ Worker 1 │  │ Worker 2 │  │ Worker 3 │  ← 每个 Worker 处理请求
    └──────────┘  └──────────┘  └──────────┘
          │              │              │
          └──────────────┴──────────────┘

                 accept_mutex 锁

              ┌──────────────────────┐
              │  epoll / kqueue / IOCP  │  ← 事件驱动,一个 Worker 处理数万连接
              └──────────────────────┘
  • Master 进程:读取和验证配置,创建/绑定 socket,管理 Worker 生命周期
  • Worker 进程:处理实际请求,每个 Worker 是单线程、事件驱动的,通过 epoll(Linux)/ kqueue(macOS)/ IOCP(Windows)同时处理数万并发连接

2.2 为什么 Nginx 这么快?

  1. 事件驱动:一个 Worker 线程处理所有请求,不阻塞等待,通过 I/O 多路复用(epoll)高效管理连接
  2. 非阻塞 I/O:读不到数据立即返回,不会让线程傻等,CPU 利用率极高
  3. 多进程 + 单线程:每个 Worker 单线程,无锁竞争,上下文切换开销极低
  4. 内存池:预分配内存池,减少频繁 malloc/free

2.3 Nginx vs Apache

维度NginxApache
并发模型事件驱动(epoll)进程/线程 per 连接
并发连接数数万(内存占用低)数千(内存占用高)
静态资源极快,自带缓存较快
动态内容反向代理到后端通过模块处理(mod_php)
配置简洁,声明式丰富,.htaccess 灵活
适用场景反向代理、负载均衡、高并发共享主机、动态内容

三、反向代理

3.1 什么是反向代理?

正向代理(代理客户端):
客户端 → [代理服务器] → 互联网
作用:翻墙、隐藏客户端 IP

反向代理(代理服务端):
客户端 → [Nginx 反向代理] → 后端服务集群
作用:隐藏服务端结构、负载均衡、SSL 卸载

3.2 基本配置

nginx
# /etc/nginx/conf.d/api.conf
server {
    listen 80;
    server_name api.example.com;

    # 反向代理到后端服务
    location /api/orders {
        proxy_pass http://localhost: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;
    }

    location /api/inventory {
        proxy_pass http://localhost:8081;
    }
}

proxy_set_header 关键说明:

Header含义后端拿到的值
X-Real-IP客户端的真实 IP$remote_addr
X-Forwarded-For经过的代理链客户端IP, 代理1, 代理2
X-Forwarded-Proto原始请求协议httphttps
Host原始请求的 Hostapi.example.com

3.3 proxy_pass 规则

nginx
# 规则1:带 URI 路径 → 替换匹配部分
location /api/ {
    proxy_pass http://backend/;  # /api/orders → http://backend/orders(/api 被替换成 /)
}

# 规则2:不带 URI 路径 → 原样拼接
location /api/ {
    proxy_pass http://backend;   # /api/orders → http://backend/api/orders(原样)
}

# 规则3:精确匹配
location = /health {
    proxy_pass http://backend;
}

四、负载均衡

4.1 upstream 模块

Nginx 的 upstream 模块定义一组后端服务器,配合 proxy_pass 实现负载均衡:

nginx
upstream order-backend {
    server 192.168.1.101:8080 weight=5;
    server 192.168.1.102:8080 weight=3;
    server 192.168.1.103:8080 weight=2 backup;  # 备用节点
}

server {
    listen 80;
    location /api/orders {
        proxy_pass http://order-backend;
        proxy_connect_timeout 3s;      # 连接超时
        proxy_read_timeout 10s;         # 读取超时
        proxy_send_timeout 10s;         # 发送超时
    }
}

4.2 6 种负载均衡策略

4.2.1 轮询(默认)

每个请求按时间顺序逐一分配到不同的后端服务器。如果某台服务器宕机,自动剔除。

nginx
upstream backend {
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
    server 192.168.1.103:8080;
}

4.2.2 加权轮询(weight)

权重越高分配到的请求越多。适合后端服务器性能不一致的场景。

nginx
upstream backend {
    server 192.168.1.101:8080 weight=5;  # 高性能机器
    server 192.168.1.102:8080 weight=3;
    server 192.168.1.103:8080 weight=2;  # 低配机器
}

4.2.3 IP Hash(ip_hash)

根据客户端 IP 的 Hash 值分配,同一客户端的请求始终落到同一台服务器。解决 Session 共享问题,但后端服务器宕机时会重新分配。

nginx
upstream backend {
    ip_hash;
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
}

注意: ip_hashweight 互斥,不能同时使用。如果需要加权 + 会话保持,建议用 Redis 集中管理 Session。

4.2.4 最少连接数(least_conn)

优先分配给当前活跃连接数最少的服务器。适合请求处理时间差异较大的场景。

nginx
upstream backend {
    least_conn;
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
}

4.2.5 URL Hash(hash $request_uri)

按请求 URL 的 Hash 分配,同一个 URL 始终落到同一台服务器。适合后端有本地缓存的场景,提高缓存命中率。

nginx
upstream backend {
    hash $request_uri;
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
}

4.2.6 一致性 Hash(hash $remote_addr consistent)

基于一致性 Hash 环分配,当服务器增减时,只有少部分请求被重新分配。适合缓存场景,减少缓存失效。

nginx
upstream backend {
    hash $remote_addr consistent;
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
    server 192.168.1.103:8080;
}

一致性 Hash 原理:

普通 Hash:增减服务器 → 所有请求重新分配 → 缓存全部失效
一致性 Hash:增减服务器 → 只有相邻节点的请求被重新分配 → 大部分缓存保留

4.3 后端状态标记

nginx
upstream backend {
    server 192.168.1.101:8080 max_fails=3 fail_timeout=30s;  # 30s 内失败 3 次则标记为 down
    server 192.168.1.102:8080 down;                            # 手动下线
    server 192.168.1.103:8080 backup;                          # 备用节点,所有正常节点挂掉后才启用
}
参数说明
max_fails=N最大失败次数
fail_timeout=N失败超时时间,超时后重新尝试
down手动标记为不可用
backup备用节点,只在其他节点都不可用时才启用

五、SSL/TLS 配置

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

    # 证书配置
    ssl_certificate     /etc/nginx/ssl/fullchain.pem;      # 公钥证书
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;        # 私钥
    ssl_session_cache   shared:SSL:10m;                    # 会话缓存 10MB
    ssl_session_timeout 10m;                               # 会话超时

    # 安全协议与加密套件
    ssl_protocols TLSv1.2 TLSv1.3;                         # 只允许 TLS 1.2+
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers on;                          # 优先使用服务端加密套件

    # 后端用 HTTP,SSL 在 Nginx 层终结
    location /api/ {
        proxy_pass http://backend;
    }
}

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

六、Gzip 压缩

nginx
http {
    gzip on;
    gzip_min_length 1024;           # 小于 1KB 不压缩,不划算
    gzip_comp_level 5;              # 压缩级别 1-9,5 是性价比最优
    gzip_types text/plain
               text/css
               text/javascript
               application/json
               application/javascript
               application/xml
               image/svg+xml;
    gzip_vary on;                   # 添加 Vary: Accept-Encoding 响应头
    gzip_disable "msie6";           # 禁用 IE6 压缩
}

gzip_comp_level 选择:

级别CPU 消耗压缩率推荐
1-3不推荐
4-6推荐 5
7-9浪费 CPU

七、缓存配置

7.1 静态资源缓存

nginx
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
    expires 30d;                            # 浏览器缓存 30 天
    add_header Cache-Control "public, immutable";
    access_log off;                         # 不记录日志
}

7.2 代理缓存

nginx
http {
    # 定义缓存路径:目录、层级、缓存大小、非活跃清理时间
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m
                     max_size=1g inactive=60m use_temp_path=off;

    server {
        location /api/ {
            proxy_cache my_cache;
            proxy_cache_key "$host$request_uri$request_body";  # 缓存键
            proxy_cache_valid 200 1m;           # 200 响应缓存 1 分钟
            proxy_cache_valid 404 10s;          # 404 缓存 10 秒
            proxy_cache_bypass $http_pragma;    # 跳过缓存的条件
            proxy_cache_revalidate on;           # 过期时重新验证
            add_header X-Cache-Status $upstream_cache_status;  # 调试用

            proxy_pass http://backend;
        }
    }
}

$upstream_cache_status 值含义:

含义
MISS未命中缓存,从后端获取
HIT命中缓存
EXPIRED缓存过期,重新验证
STALE后端异常,返回过期缓存
BYPASS跳过缓存

八、限流

8.1 请求频率限制(控制 QPS)

nginx
http {
    # 定义限流区域:10MB 存储约 16 万个 IP 的状态
    limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;

    server {
        location /api/ {
            limit_req zone=req_limit burst=20 nodelay;
            # burst=20:允许 20 个突发请求排队
            # nodelay:排队中的请求立即处理,不延迟
            proxy_pass http://backend;
        }
    }
}

参数解释:

参数含义
rate=10r/s每秒允许 10 个请求(平均 100ms 一个)
burst=20突发队列长度,超过 rate 的请求排队等待
nodelay突发请求立即处理,不按 rate 均匀延迟
delay=10突发队列中前 10 个立即处理,其余延迟(替代 nodelay 的精细控制)

8.2 并发连接数限制

nginx
http {
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

    server {
        location /api/ {
            limit_conn conn_limit 5;          # 每个 IP 最大 5 个并发连接
            limit_conn_status 429;            # 超限返回 429 Too Many Requests
            proxy_pass http://backend;
        }
    }
}

8.3 下载速度限制

nginx
location /downloads/ {
    limit_rate 500k;              # 限制每个连接的速度为 500KB/s
    limit_rate_after 10m;         # 下载 10MB 后才开始限速
}

九、动静分离

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

    # 静态资源:Nginx 直接返回
    location / {
        root /var/www/html;               # 前端静态文件目录
        index index.html;
        try_files $uri $uri/ /index.html; # SPA 模式,找不到文件返回 index.html
    }

    # 动态请求:反向代理到后端
    location /api/ {
        proxy_pass http://backend;
    }
}

十、WebSocket 代理

nginx
location /ws/ {
    proxy_pass http://backend;
    proxy_http_version 1.1;                         # WebSocket 需要 HTTP/1.1
    proxy_set_header Upgrade $http_upgrade;         # 升级协议
    proxy_set_header Connection "upgrade";          # 保持连接
    proxy_read_timeout 3600s;                       # 长连接超时
    proxy_send_timeout 3600s;
}

十一、Nginx 在微服务架构中的位置

                    ┌─────────────────────────┐
                    │   Nginx(服务端负载均衡)   │  ← 统一入口、SSL、限流、静态资源
                    └──────────┬──────────────┘

              ┌────────────────┼────────────────┐
              ▼                ▼                ▼
        ┌──────────┐   ┌──────────┐    ┌──────────┐
        │ Gateway  │   │ Gateway  │    │ Gateway  │  ← 微服务网关
        └────┬─────┘   └────┬─────┘    └────┬─────┘
             │               │               │
             └───────────────┼───────────────┘


              ┌──────────────────────────┐
              │  Ribbon / LoadBalancer    │  ← 客户端负载均衡
              │  (服务间调用)             │
              └──────────────────────────┘

Nginx 和 Ribbon/LoadBalancer 的分工:

NginxRibbon / LoadBalancer
类型服务端负载均衡(中心化)客户端负载均衡(去中心化)
位置系统最外层入口服务间内部调用
流量类型南北向(外部→内部)东西向(服务→服务)
策略6 种(轮询、加权、IP Hash、最小连接、URL Hash、一致性 Hash)Ribbon 7 种 / LoadBalancer 2-3 种
SSL在 Nginx 层终结内网 HTTP,不需要

十二、常用命令

bash
# 启动
nginx

# 停止(优雅,等待处理完当前请求)
nginx -s quit

# 立即停止
nginx -s stop

# 重载配置(不中断服务)
nginx -s reload

# 重新打开日志文件
nginx -s reopen

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

# 测试指定配置文件
nginx -t -c /etc/nginx/nginx.conf

# 查看版本
nginx -v

十三、面试要点

Q:Nginx 如何处理高并发?

Master-Worker 多进程模型 + 事件驱动(epoll)+ 非阻塞 I/O。每个 Worker 单线程处理,通过 epoll 同时监听数万连接,有事件才处理,不阻塞等待。配合 sendfile 系统调用实现零拷贝静态文件传输。

Q:Nginx 有哪几种负载均衡策略?

轮询(默认)、加权轮询(weight)、IP Hash(ip_hash)、最少连接数(least_conn)、URL Hash(hash $request_uri)、一致性 Hash(hash $remote_addr consistent)。

Q:正向代理和反向代理的区别?

正向代理代理客户端,客户端知道目标服务器但通过代理访问(如翻墙);反向代理代理服务端,客户端只知道 Nginx 地址,不知道后端真实服务器。

Q:Nginx 的 location 匹配优先级?

= 精确匹配 > ^~ 前缀匹配(不检查正则) > ~~* 正则匹配(按书写顺序) > 普通前缀匹配(最长匹配优先)。

Q:如何实现 Nginx 高可用?

通过 Keepalived 实现 VIP(虚拟 IP)漂移。两台 Nginx 共享一个虚拟 IP,主节点故障时备节点自动接管。同时配合 upstream 的健康检查,自动剔除故障后端节点。