Nginx “增广见闻”

184 阅读2分钟

一、高级配置技巧

1. 动态分流与灰度发布

使用 split_clients 模块实现按比例分流请求,常用于 AB 测试或灰度发布:

split_clients "${remote_addr}AAA" $variant {
    50%   "backend_v1";
    50%   "backend_v2";
}

location / {
    proxy_pass http://$variant;
}

2. 条件映射请求头

利用 map 指令动态设置变量,例如根据 User-Agent 分类请求:

map $http_user_agent $is_mobile {
    default         0;
    "~*android|iphone" 1;
}

server {
    if ($is_mobile) {
        rewrite ^ /mobile redirect;
    }
}

3. 动态生成响应内容

无需后端,直接通过 Nginx 返回内容:

location /hello {
    add_header Content-Type text/plain;
    return 200 "Hello, World!\nHost: $host\nURI: $request_uri";
}

二、性能优化

1. TCP 连接复用

提升反向代理性能,复用后端连接:

upstream backend {
    server 10.0.0.1:80;
    keepalive 32;  # 保持长连接
}

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

2. 静态文件高效传输

启用内存缓存和零拷贝技术:

sendfile       on;
tcp_nopush     on;     # 数据包累积到一定大小再发送
tcp_nodelay    on;     # 禁用 Nagle 算法
aio            on;     # 异步文件读取(需 Linux 内核支持)

3. 动态压缩优化

精细控制 Gzip 压缩,避免压缩小文件:

gzip            on;
gzip_min_length 1024;   # 小于 1KB 不压缩
gzip_comp_level 5;
gzip_types      text/plain application/json;

三、安全增强

1. 请求频率限制

防御暴力攻击,限制同一 IP 的请求速率:

limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

location /api/ {
    limit_req zone=api_limit burst=20 nodelay;
    proxy_pass http://backend;
}

2. 敏感路径隐藏

通过随机化路径防止扫描:

location ~ ^/admin-(?!xyz123)[a-zA-Z0-9]+$ {
    # 仅当路径包含 "xyz123" 时才允许访问
    proxy_pass http://backend_admin;
}

3. 安全头配置

强制安全策略:

add_header X-Content-Type-Options "nosniff";
add_header Content-Security-Policy "default-src 'self'";
add_header X-Frame-Options "DENY";

四、调试与日志

1. 条件日志记录

仅记录特定请求(如 POST 或错误状态码):

map $request_method $loggable {
    default         0;
    POST            1;
}

map $status $log_status {
    ~^[45]          1;
    default         0;
}

access_log /var/log/nginx/important.log combined if=$loggable;
access_log /var/log/nginx/errors.log combined if=$log_status;

2. 实时调试变量

输出变量值到响应头,方便调试:

add_header X-Debug-Host "$host";
add_header X-Debug-Remote-IP "$remote_addr";

五、四层代理与 UDP

Nginx 的 stream 模块支持 TCP/UDP 代理(如数据库负载均衡):

stream {
    upstream dns_servers {
        server 10.0.0.1:53;
        server 10.0.0.2:53;
    }

    server {
        listen 53 udp;
        proxy_pass dns_servers;
    }
}

六、实用冷知识

  1. 优雅关闭 Worker 进程
    向旧进程发送 SIGQUIT,处理完当前请求后退出:

    kill -QUIT `cat /run/nginx.pid`
    
  2. 复用配置变量
    set 定义变量简化复杂逻辑:

    set $cache_key "$host$request_uri";
    proxy_cache_key $cache_key;
    
  3. GeoIP 拦截
    根据地理位置拒绝访问(需 ngx_http_geoip_module):

    geoip_country /etc/nginx/GeoIP.dat;
    location / {
        if ($geoip_country_code = CN) { return 403; }
    }
    

七、注意事项

  • 慎用 if 指令:在 location 中使用 if 可能导致性能问题,优先使用 mapsplit_clients
  • 缓存失效:动态内容避免过度缓存,可通过 proxy_cache_bypass 控制。
  • 正则优化:正则匹配(如 ~*)较耗时,尽量在 location 外层过滤。

以上技巧可根据场景组合使用,建议结合官方文档和实际需求调整参数。