Skip to content
第 210 / 250 章运维⏱ 12 分钟阅读

第 210 章:Nginx 进阶配置

学习目标

  • 掌握 location 匹配规则
  • 学会多级缓存
  • 配置防盗链与跨域
  • 实现灰度发布

一、location 匹配规则

nginx
location [modifier] pattern {
    ...
}
modifier匹配方式优先级
=精确1(最高)
^~前缀,匹配后不再正则2
~正则(区分大小写)3
~*正则(不区分大小写)3
(无)前缀4(最低)

例子

nginx
# 1. 精确 =
location = /login {
    return 200 "登录页";
}

# 2. 前缀(优先)
location ^~ /static/ {
    root /var/www;
}

# 3. 正则
location ~ \.(gif|jpg|png)$ {
    expires 30d;
}

location ~* \.(GIF|JPG)$ {
    # 同上,不区分大小写
}

# 4. 普通前缀
location /api {
    proxy_pass http://backend;
}

匹配示例:

GET /static/img.jpg
→ ^~ /static/ 命中 (前缀优先)
GET /login
→ = /login 命中 (精确优先)

二、URL 重写

2.1 rewrite

nginx
location /old {
    rewrite ^/old/(.*)$ /new/$1 permanent;  # 301
}

location /api {
    rewrite ^/api/(.*)$ /$1 break;
}

2.2 return

nginx
location /admin {
    return 403;
}

location /google {
    return 301 https://www.google.com;
}

2.3 try_files

nginx
location / {
    try_files $uri $uri/ /index.html;
    # 找不到 $uri → 找 $uri/ 目录 → fallback 到 /index.html
}

location /static {
    try_files $uri =404;
}

三、防盗链

nginx
location ~* \.(jpg|jpeg|png|gif|webp)$ {
    valid_referers none blocked *.example.com example.com;
    if ($invalid_referer) {
        return 403;
    }
}

四、跨域 CORS

nginx
location /api/ {
    # 允许的源
    add_header Access-Control-Allow-Origin "https://example.com" always;
    add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
    add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
    add_header Access-Control-Allow-Credentials "true" always;
    add_header Access-Control-Max-Age 86400;

    # OPTIONS 直接 204
    if ($request_method = OPTIONS) {
        return 204;
    }

    proxy_pass http://backend;
}

五、灰度发布

nginx
upstream backend_v1 {
    server 192.168.1.1:3000;
}

upstream backend_v2 {
    server 192.168.1.2:3000;
}

server {
    location / {
        # 灰度用户(cookie 中带 beta=1)到 v2
        if ($cookie_beta = "1") {
            proxy_pass http://backend_v2;
        }

        # 默认 v1
        proxy_pass http://backend_v1;
    }
}

5.2 基于权重

nginx
upstream backend {
    server 192.168.1.1:3000 weight=9;   # 90% 到 v1
    server 192.168.1.2:3000 weight=1;   # 10% 到 v2
}

5.3 基于 IP

nginx
geo $gray_release {
    default 0;
    192.168.1.0/24 1;   # 内部 IP 灰度
    10.0.0.0/8 1;
}

server {
    location / {
        if ($gray_release = 1) {
            proxy_pass http://backend_v2;
        }
        proxy_pass http://backend_v1;
    }
}

六、动静分离

nginx
server {
    # 静态资源
    location ~* \.(html|css|js|jpg|png|gif|ico|woff|ttf)$ {
        root /var/www/static;
        expires 30d;
        access_log off;
    }

    # API 走后端
    location /api/ {
        proxy_pass http://backend;
    }
}

七、多级缓存

nginx
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=cache_static:10m
                 max_size=10g inactive=30d use_temp_path=off;

server {
    location / {
        proxy_pass http://backend;
        proxy_cache cache_static;

        # 不同状态码不同缓存
        proxy_cache_valid 200 10m;
        proxy_cache_valid 301 1h;
        proxy_cache_valid 404 1m;
        proxy_cache_valid any 5s;

        # 缓存条件
        proxy_cache_methods GET HEAD;
        proxy_cache_min_uses 2;        # 至少被请求 2 次才缓存
        proxy_cache_key "$scheme$host$request_uri";

        # 命中状态
        add_header X-Cache-Status $upstream_cache_status;

        # 绕过条件
        proxy_cache_bypass $http_cache_control;
    }
}

主动清理缓存

bash
# 删除指定 key
rm -rf /var/cache/nginx/c/3a/1234567890abc...

或使用 ngx_cache_purge 模块:

nginx
location ~ /purge(/.*) {
    proxy_cache_purge cache_static $scheme$host$1;
}

八、安全加固

8.1 安全头

nginx
server {
    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 "no-referrer-when-downgrade" always;
    add_header Content-Security-Policy "default-src 'self'" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}

8.2 限制请求体大小

nginx
client_max_body_size 10M;

8.3 隐藏版本号

nginx
server_tokens off;

8.4 限速

nginx
http {
    limit_req_zone $binary_remote_addr zone=global:10m rate=10r/s;

    server {
        location / {
            limit_req zone=global burst=20 nodelay;
            limit_req_status 429;
        }
    }
}

8.5 阻止常见攻击

nginx
# 阻止常见 User-Agent
if ($http_user_agent ~* "scrapy|curl|wget|bot") {
    return 403;
}

# 阻止特定文件
location ~ /\.(git|svn|env) {
    deny all;
}

九、WebSocket

nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    location /ws/ {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
    }
}

十、监控

10.1 状态页

nginx
location /nginx_status {
    stub_status;
    allow 127.0.0.1;
    deny all;
}
Active connections: 2
server accepts handled requests
 100 100 200
Reading: 0 Writing: 1 Waiting: 1

10.2 Prometheus exporter

bash
nginx_exporter -nginx.scrape-uri=http://localhost/nginx_status

十一、常见问题

11.1 配置不生效

bash
nginx -t             # 测试语法
nginx -s reload      # 重载

11.2 502 Bad Gateway

  • 后端服务没启动
  • 端口被防火墙挡
  • proxy_pass 配置错

11.3 跨域头重复

后端已经设置 CORS 头,前端再添加会重复。

解决:删一个,推荐只在前端 Nginx 设置。

11.4 大文件上传

nginx
client_max_body_size 100M;
client_body_buffer_size 128k;
proxy_read_timeout 300s;

十二、生产配置模板

nginx
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;

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

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    charset utf-8;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 30;
    keepalive_requests 100;

    server_tokens off;
    client_max_body_size 50M;

    gzip on;
    gzip_vary on;
    gzip_min_length 1k;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml;

    # 日志
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    'rt=$request_time uct=$upstream_connect_time urt=$upstream_response_time';
    access_log /var/log/nginx/access.log main;

    # 限流
    limit_req_zone $binary_remote_addr zone=api:10m rate=30r/s;

    include /etc/nginx/conf.d/*.conf;
}

十三、本章小结

技巧用途
location 规则URL 匹配
rewrite / returnURL 重写
try_filesSPA fallback
if + geo灰度发布
add_headerCORS / 安全头
limit_req限流

动手练习

  1. 实现 SPA History fallback
  2. 配置灰度发布(基于 IP / Cookie)
  3. 加安全头 + 限流
  4. 配置 WebSocket 反向代理

推荐阅读


下一章:第 211 章:Docker 入门与容器化

本站基于 VitePress 构建 · 由 Codebook 团队维护