Nginx 常见配制

154 阅读8分钟

Nginx 是什么

Nginx 是一个高性能的 Web 服务器,也常被用作反向代理、负载均衡器和 HTTP 缓存工具。它像一个“门卫”,根据配置文件 nginx.conf,决定每个请求的去向。

拦截URL配制

nginx 会根据 location 分辨 url , 让 符合条件的 url 执行对应的逻辑. 像一个 switch

location = /111/ { 
	default_type text/plain; 
	return 200 "111 success"; 
}

拦截规则

匹配方式示例特点优先级
精确匹配location = /exact路径必须完全匹配最高
高优先级前缀location ^~ /prefix匹配前缀,优先级高于正则第二
正则匹配location ~ /a.*\.html区分大小写正则第三
正则匹配(忽略大小写)location ~* /a.*\.html忽略大小写正则第三
普通前缀匹配location /common匹配路径前缀,常用于默认配置最低

精确匹配(=) > 高优先级前缀匹配(^~) > 正则匹配(~ ~*) > 普通前缀匹配

URL 分配配制

分配静态资源

  • root 和 alias 会设置静态资源路经 , 让 url 访问到对应的资源
  • 差异: root 是“补全路径”,alias 是“替换路径”。
  • 在使用 正则匹配 location 时, 必须 有捕获组, 否则 会引起错误
location /static/ {
    root /data/images/;  # 访问 http://localhost:80/static/logo.png → /data/images/static/logo.png
}
location /static/ {
    alias /data/images/;  # 访问 http://localhost:80/static/logo.png → /data/images/logo.png
}

解析 在访问 http://localhost:80/static/logo.png 时, 配制 root 会到 /data/images/static/logo.png 而 alias 会到 /data/images/logo.png 没有 location 所匹配的路经

分配反向代理

  • 反向代理 是站在 客户端的角度来看待的. 客户端访问 nginx , nginx 分配到 目标服务中. 对于 目标服务来说, nginx 是它的代理. 对于客户端来说 就是反向的一个代理.
  • 反向代理的作用:
    • 负载均衡: 将用户请求分发到多个服务器,避免单点过载。
    • 安全防护: 隐藏后端服务器 IP,防止 DDoS 攻击。
    • 统一入口: 对外提供单一域名和端口,内部可部署多个服务(如微服务网关)。
    • 性能优化: 通过缓存、压缩、SSL 卸载提升响应速度。

安全防护 & 统一入口

# 访问 /api 的请求, 都会转接到 http://192.168.1.6:3000
location ^~ /api { 
    proxy_pass http://192.168.1.6:3000;
}

location ^~ /user_api { 
    proxy_pass http://192.168.1.6:3001;
}
sequenceDiagram
    participant Client as 客户端
    participant Nginx as Nginx
    participant Backend1 as 后端服务1 (3000)
    participant Backend2 as 后端服务2 (3001)

    Note over Client: 发起请求
    Client->>Nginx: GET /api/user/info
    Nginx->>Nginx: 路由匹配检查
    alt 路径匹配 /api
        Nginx->>Backend1: 代理请求 → http://192.168.1.6:3000/api/user/info
        Backend1-->>Nginx: 返回响应数据
    else 路径匹配 /user_api
        Nginx->>Backend2: 代理请求 → http://192.168.1.6:3001/user_api/...
        Backend2-->>Nginx: 返回响应数据
    end
    Nginx-->>Client: 返回最终响应

负载均衡

  • 作用:Nginx 可以将进入的请求流量均匀分发到多个后端服务器(如应用服务节点),从而实现负载均衡,提升系统的吞吐量、响应能力和整体可用性。
  • 缺点:传统基于 Nginx 的负载均衡方式通常需要预先配置好所有后端服务器,这些服务器需始终处于运行状态。这种方式有两个主要问题:
    1. 资源浪费:在低流量时段,闲置的服务器仍在运行,造成资源浪费。
    2. 扩展困难:在流量高峰期,如果没有提前部署足够的服务器,容易导致系统负载过高甚至崩溃。
  • 对比k8s : 在现代云原生架构中,常常使用 Kubernetes(k8s)来动态管理服务的生命周期与扩缩容。Nginx 则更多作为接入层反向代理,与 Kubernetes 的服务发现和负载均衡机制集成使用,起到入口网关(如 Ingress Controller)的作用。
负载均衡策略
策略说明适用场景
默认轮询依次轮流分配请求服务性能均衡
加权轮询设置权重决定流量比例服务性能差异较大
最少连接分配给当前连接最少的节点长连接服务,如 WebSocket
IP 哈希同一客户端 IP 分配固定节点会话保持(购物车等)
备用服务器主服务器宕机才启用备用节点灾备方案
轮询分配
  • nginx 的默认策略, 对所有服务器一视同仁, 根据顺序 分配.
  • 适合后端服务器性能均匀的无状态服务(如 REST API、静态资源)。
http {
   # 定义后端服务器组(upstream)
   upstream backend_servers {
       # 基础轮询策略(默认)
       server 192.168.1.101:8080;
       server 192.168.1.102:8080;
       server 192.168.1.103:8080;
   }
   server {
       listen 80;
       server_name example.com;
       location / {
           # 将请求代理到后端服务器组
           proxy_pass http://backend_servers;
       }
   }
}
加权轮询
  • 使用 weight 设置比重, weight 越大, 流量越大
  • 适合后端服务器配置不均(如新旧硬件混用)。
upstream backend {
    server 192.168.1.1:80 weight=3;  # 处理3倍流量
    server 192.168.1.2:80 weight=1;
}
最少连接数
  • 优先分配给当前连接数最少的服务器​​
  • 适合长连接服务(如 WebSocket、数据库连接池)
upstream backend {
    least_conn;
    server 192.168.1.1:80;
    server 192.168.1.2:80;
}
IP哈希(IP Hash)
  • 同一客户端IP固定访问同一后端​​(会话保持)
  • 适合 需要会话一致性的服务(如用户登录状态、购物车)
upstream backend {
    ip_hash;
    server 192.168.1.1:80;
    server 192.168.1.2:80;
}
备用服务器
  • 设置该服务只会在其他服务都挂掉的情况下才使用
  • 适合 最后的防线
upstream backend_api {
    server 192.168.1.6:3000 weight=2;  # 权重2
    server 192.168.1.7:3000;           # 权重1
    server 192.168.1.8:3000 backup;    # 备用服务器
}
Nginx 连接池
  • Nginx 和 目标服务器 连接时, 会有 TCP 行为. 这会产生不必要的 三次握手. Nginx 会保留已创建好的连接, 来减少 TCP 行为
upstream backend {
    server 192.168.1.101:8080;
    keepalive 32;       # 空闲连接池最大容量 = 32
    keepalive_timeout 60s;  # 空闲连接超过 60 秒自动关闭
}

server {
    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

运行行为
  1. Nginx 连接池会在有连接时, 创建连接, 而并非 keepalive 设置多少就创建多少 keepalive 是指最多保留多少连接.
  2. Nginx 连接池中的连接不会一直保留,是根据 keepalive_timeout 设置的持续时间关闭的.
graph LR
A[客户端请求] --> B{Nginx}
B --> C{连接池有空闲?}
C -->|有| D[复用连接]
C -->|无| E[新建连接]
D --> F[发送请求到后端]
E --> F
F --> G{请求完成}
G --> H{连接池未满?}
H -->|未满| I[放回连接池]
H -->|已满| J[关闭连接]
I --> K{闲置超时? keepalive_timeout}
K -->|超时| J
K -->|未超时| I

灰度环境

  • 灰度环境 即 新功能 + 线上环境的环境. 可以在 正式环境中进行小范围的访问新功能.
  • 作用:
    • 灰度测试
    • AB对照
    • 减少风险
    • 逐步发布与监控
灰度环境策略
灰度策略条件来源适用场景
Cookie / Session用户身份标记内测用户、VIP 抢先体验
IP 地址网络来源地域灰度、局域网优先
请求头A/B 测试标记功能测试、多版本切换
百分比预设随机分流逐步上线新功能
基于用户 Cookie 或 Session 的灰度发布
  • 用于:
    • 测试人员进行灰度测试
    • VIP 抢先体验新功能
server {
    listen 80;
    server_name example.com;

    location / {
        # 判断用户是否有灰度发布标识
        if ($http_cookie ~* "gray_test=true") {
            # 如果用户标记为灰度用户,转发到新功能的服务
            proxy_pass http://new_feature_backend;  # 新功能后端服务
        }
        else {
            # 否则,转发到旧版本的服务
            proxy_pass http://old_feature_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 $scheme;
    }
}
基于 IP 地址的灰度发布
  • 用于 :
    • 按地区或网络环境发布新功能
    • 限定某些区域的灰度发布
http {
    upstream old_backend {
        server old_feature_backend;
    }

    upstream new_backend {
        server new_feature_backend;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            # 假设使用 IP 地址哈希来进行灰度发布
            set $is_gray 0;
            if ($remote_addr ~* "^(192\.168\.1\.[0-9]{1,3})$") {
                set $is_gray 1;  # 某些 IP 范围分配到新功能
            }

            if ($is_gray = 1) {
                proxy_pass http://new_backend;
            }
            else {
                proxy_pass http://old_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 $scheme;
        }
    }
}

基于请求头的灰度发布(AB 测试)
  • 用途
    • AB 测试和功能实验
    • 多版本并行测试
server {
    listen 80;
    server_name example.com;

    location / {
        # 假设通过 HTTP 请求头中的 X-Version 标识来区分版本
        if ($http_x_version = "new") {
            proxy_pass http://new_feature_backend;  # 新版本服务
        }
        else {
            proxy_pass http://old_feature_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 $scheme;
    }
}

基于百分比的灰度发布
  • 作用
    • 逐步发布新功能
    • 风险控制和流量管理
server {
    listen 80;
    server_name example.com;

    location / {
        # 随机分配请求
        set $random_number $math_random;

        # 设置阈值,假设将 30% 的流量分配给新功能
        if ($random_number < 0.3) {
            proxy_pass http://new_feature_backend;  # 新功能服务
        }
        else {
            proxy_pass http://old_feature_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 $scheme;
    }
}

缓存

Nginx 的 HTTP 缓存功能主要用于提升网站性能和减轻后端服务器负担。它通常用于反向代理场景,通过缓存静态或动态请求的响应结果,避免频繁访问后端。

缓存区域统一定义
http {
    proxy_cache_path /var/cache/nginx             # 缓存文件存储目录
                    levels=1:2                    # 目录结构层级,提升查找效率
                    keys_zone=my_cache:50m        # 定义缓存区域名和内存大小(索引)
                    max_size=2g                   # 最大磁盘缓存空间
                    inactive=60m                  # 超过 60 分钟未访问将被移除
                    use_temp_path=off;            # 提升缓存写入性能,避免临时路径

    include /etc/nginx/conf.d/*.conf;             # 载入其他配置文件
}

反向代理缓存后端接口(适用于 GET 查询类 API)

  • 目的: 减少后端压力,加快响应速度。
  • 场景: 常用在 内容不频繁变更 的接口
location ~* ^/api/(posts|users|ranking)/ {
    proxy_pass http://backend;

    proxy_cache my_cache;                         # 使用名为 my_cache 的缓存区域
    proxy_cache_valid 200 10m;                    # 对 200 响应缓存 10 分钟
    proxy_cache_methods GET HEAD;                 # 仅缓存 GET 和 HEAD 方法
    proxy_cache_use_stale error timeout updating; # 后端出错或更新时使用旧缓存响应

    add_header X-Cache-Status $upstream_cache_status; # 添加缓存状态头部(HIT/MISS/BYPASS)
}

缓存动态页面(如文章页、商品详情页)

  • 目的: 加快页面加载速度,适用于不登录状态下的页面访问。
  • 场景: 常用在 不频繁变化的页面
location /article/ {
    proxy_pass http://backend;

    proxy_cache my_cache;
    proxy_cache_key "$scheme$host$request_uri";   # 自定义缓存 key,避免参数造成缓存穿透
    proxy_cache_valid 200 302 5m;                 # 对 200 和 302 响应缓存 5 分钟

    proxy_cache_bypass $cookie_auth;              # 有 auth cookie 时不使用缓存
    proxy_no_cache $cookie_auth;                  # 有 auth cookie 时不保存缓存

    add_header X-Cache $upstream_cache_status;
}

静态资源缓存加速

  • 目的: 充分利用浏览器缓存,减少资源重复加载,降低带宽压力。
  • 场景: 静态资源
location ~* \.(jpg|jpeg|png|gif|css|js|ico|woff|woff2|ttf|eot)$ {
    root /var/www/public;
    expires 30d;        # 告诉浏览器此文件可缓存 30 天
    access_log off;     # 禁止记录访问日志,减少磁盘 IO
}

微服务内部接口缓存

  • 目的: 减轻内部公共服务负载,避免重复获取重复数据。
  • 场景: 内部常用的接口
location /internal/metadata {
    proxy_pass http://internal-service;

    proxy_cache my_cache;
    proxy_cache_valid 200 5m;                     # 缓存 200 响应 5 分钟
    proxy_cache_lock on;                          # 多个请求同时来时只允许第一个穿透后端
    proxy_cache_use_stale updating;               # 后端更新期间使用旧缓存
}

补充场景

前端部署和后端 fallback

  • 目的: 尝试使用 某个目录
  • 场景: 静态网址部署
location / {
  try_files $uri $uri/ /index.html;
}
graph LR
    A[用户请求路径] --> B{文件是否存在 $uri}
    B -- 是 --> R1[返回 $uri 内容]
    B -- 否 --> C{是否存在目录 $uri/}
    C -- 是 --> R2[返回 $uri/ 目录索引或内容]
    C -- 否 --> D[返回 /index.html]

配制 header 头

  • 目的: 修改 header 头, 适配请求
  • 场景: 需要携带客户端参数, 接口特殊配制
location /api/ {
  proxy_pass http://backend:3000;
  proxy_set_header Host $host; # 请求原始的 Host
  proxy_set_header X-Real-IP $remote_addr; # 请求者真实 IP
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 转发链条上的 IP 列表,追加当前客户端 IP
}

gzip 压缩配置

  • 目的: 压缩静态资源提高传输效率
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_min_length 1k;
gzip_comp_level 6;

限速限流

  • 目的: 防止爬虫或攻击设置
http {
  limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=1r/s;
  server {
    location /api/ {
      limit_req zone=req_limit_per_ip burst=5 nodelay; # 每个 IP 每秒 1 个请求,最多突发 5 个
    }
  }
}

Nginx + WebSocket 支持

location /ws/ {
  proxy_pass http://localhost:3001;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
}

直给内容

location = /111/ { 
	default_type text/plain; 
		return 200 "111 success"; 
}