Nginx配置实战:从反向代理到负载均衡的完整指南

4 阅读2分钟

摘要:Nginx是Web开发绑不开的基础设施。本文用实际配置案例覆盖反向代理、负载均衡、HTTPS、缓存、限流、WebSocket等常见场景,每段配置都可以直接拿去用。

基础配置结构

# /etc/nginx/nginx.conf 主配置
user www-data;
worker_processes auto;          # 自动匹配CPU核心数
worker_rlimit_nofile 65535;     # 最大文件描述符

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

http {
    include 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;
    
    # 性能优化
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    
    # Gzip压缩
    gzip on;
    gzip_min_length 1024;
    gzip_types text/plain text/css application/json application/javascript text/xml;
    gzip_vary on;
    
    include /etc/nginx/conf.d/*.conf;
}

场景1:反向代理

最常见的用法——把请求转发给后端服务:

# /etc/nginx/conf.d/api.conf
server {
    listen 80;
    server_name api.example.com;
    
    location / {
        proxy_pass http://127.0.0.1:8000;
        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;
        
        # 超时设置
        proxy_connect_timeout 10s;
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;
    }
}

场景2:负载均衡

upstream backend {
    # 加权轮询
    server 10.0.0.1:8000 weight=3;
    server 10.0.0.2:8000 weight=2;
    server 10.0.0.3:8000 weight=1;
    
    # 备用服务器(其他都挂了才用)
    server 10.0.0.4:8000 backup;
    
    # 健康检查
    server 10.0.0.5:8000 max_fails=3 fail_timeout=30s;
    
    # 保持连接池
    keepalive 32;
}

server {
    listen 80;
    server_name app.example.com;
    
    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";  # 配合keepalive
    }
}

其他负载均衡策略:

upstream backend {
    ip_hash;           # 同一IP固定到同一后端(会话保持)
    # least_conn;      # 最少连接数
    # hash $request_uri consistent;  # 一致性哈希
    
    server 10.0.0.1:8000;
    server 10.0.0.2:8000;
}

场景3:HTTPS配置

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

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;
    
    # 证书
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # SSL优化
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    
    # HSTS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
    }
}

Let's Encrypt自动续期:

# 安装certbot
apt install certbot python3-certbot-nginx

# 申请证书
certbot --nginx -d example.com -d www.example.com

# 自动续期(certbot安装时已配置cron)
certbot renew --dry-run

场景4:静态文件服务

server {
    listen 80;
    server_name static.example.com;
    root /var/www/static;
    
    # 缓存策略
    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
    
    location ~* \.(css|js)$ {
        expires 7d;
        add_header Cache-Control "public";
    }
    
    location ~* \.(woff2?|ttf|eot)$ {
        expires 365d;
        add_header Cache-Control "public, immutable";
    }
    
    # 防盗链
    location ~* \.(jpg|jpeg|png|gif)$ {
        valid_referers none blocked example.com *.example.com;
        if ($invalid_referer) {
            return 403;
        }
    }
}

场景5:WebSocket代理

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

server {
    listen 80;
    server_name ws.example.com;
    
    location /ws {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        
        # WebSocket长连接超时
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
}

场景6:限流

# 定义限流规则
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

server {
    listen 80;
    server_name api.example.com;
    
    # API限流:每秒10个请求,突发允许20个排队
    location /api/ {
        limit_req zone=api_limit burst=20 nodelay;
        limit_req_status 429;
        
        proxy_pass http://127.0.0.1:8000;
    }
    
    # 连接数限制:每IP最多50个连接
    location / {
        limit_conn conn_limit 50;
        proxy_pass http://127.0.0.1:8000;
    }
}

场景7:前后端分离部署

server {
    listen 80;
    server_name app.example.com;
    root /var/www/frontend/dist;
    
    # 前端SPA路由
    location / {
        try_files $uri $uri/ /index.html;
    }
    
    # API转发到后端
    location /api/ {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    # 静态资源缓存
    location /assets/ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

常用运维命令

# 测试配置语法
nginx -t

# 平滑重载(不中断服务)
nginx -s reload

# 查看当前连接状态
curl http://localhost/nginx_status
# 需要配置:
# location /nginx_status {
#     stub_status on;
#     allow 127.0.0.1;
#     deny all;
# }

# 实时查看访问日志
tail -f /var/log/nginx/access.log

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

# 统计最慢的请求
awk '{print $NF, $7}' /var/log/nginx/access.log | sort -rn | head -20

总结

Nginx配置的核心就是几个场景的组合:

  • 反向代理 + HTTPS = 标准Web服务
  • 负载均衡 + 健康检查 = 高可用
  • 限流 + 缓存 = 性能和安全
  • 静态文件 + SPA路由 = 前后端分离

建议把常用配置做成模板,新项目直接复制修改,比每次从头写快得多。