找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2085

积分

0

好友

273

主题
发表于 4 小时前 | 查看: 2| 回复: 0

本文整理了 Nginx 在生产环境中常见的问题及解决方案,涵盖配置、性能、安全、故障排查等多个方面,帮助开发者快速定位和解决问题。

目录

  • 一、安装与启动问题
  • 二、配置相关问题
  • 三、反向代理与负载均衡
  • 四、性能优化问题
  • 五、SSL/HTTPS 问题
  • 六、安全相关问题
  • 七、日志与故障排查
  • 八、实际案例场景

一、安装与启动问题

1.1 Nginx 启动失败

问题现象

$ nginx
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)

原因分析

  • 端口已被其他进程占用(常见:Apache、另一个 Nginx 实例)
  • 权限不足(80/443 端口需要 root 权限)

解决方案

# 1. 查看端口占用
sudo lsof -i :80
sudo netstat -tlnp | grep :80
sudo ss -tlnp | grep :80

# 2. 停止占用进程
sudo kill -9 <PID>

# 3. 或者修改 Nginx 端口
# /etc/nginx/nginx.conf
server {
    listen 8080;  # 改用非特权端口
    # ...
}

# 4. 检查配置语法
sudo nginx -t

# 5. 查看错误日志
sudo tail -f /var/log/nginx/error.log

1.2 权限问题导致启动失败

问题现象

nginx: [emerg] open() "/var/log/nginx/access.log" failed (13: Permission denied)

解决方案

# 1. 检查日志目录权限
ls -la /var/log/nginx/

# 2. 修正权限
sudo chown -R nginx:nginx /var/log/nginx/
sudo chmod -R 755 /var/log/nginx/

# 3. 或者修改配置中的日志路径
# /etc/nginx/nginx.conf
error_log /tmp/nginx_error.log;
access_log /tmp/nginx_access.log;

1.3 worker 进程数配置问题

问题现象
CPU 使用率异常或进程数过多

解决方案

# /etc/nginx/nginx.conf
# 推荐设置为 CPU 核心数
worker_processes auto;  # 自动检测

# 或手动指定
# worker_processes 4;

# 查看 CPU 核心数
nproc

# 绑定 CPU 亲和性(高性能场景)
worker_cpu_affinity auto;

二、配置相关问题

2.1 配置文件语法错误

问题现象

$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax failed
nginx: [emerg] unknown directive "server_nam" in /etc/nginx/conf.d/site.conf:10

解决方案

# 1. 测试配置语法
sudo nginx -t

# 2. 详细错误输出
sudo nginx -T 2>&1 | head -50

# 3. 常见错误检查清单
# - 缺少分号
# - 括号不匹配
# - 指令拼写错误
# - 使用了未加载模块的指令

# 4. 分段测试配置
# 注释掉部分配置,逐步排查

配置检查清单

# ✅ 正确示例
server {
    listen 80;
    server_name example.com;
    root /var/www/html;
    index index.html;
}

# ❌ 常见错误
server {
    listen 80          # 缺少分号
    server_name example.com
    root /var/www/html  # 缺少分号
    index index.html
}                      # 缺少闭合括号

2.2 server_name 不匹配问题

问题现象

  • 访问域名时返回默认页面或 404
  • 多个 server 块配置冲突

解决方案

# server_name 匹配优先级:
# 1. 精确匹配 > 2. 通配符 > 3. 正则 > 4. default_server

server {
    listen 80;
    server_name www.example.com example.com;
    # 精确匹配
}

server {
    listen 80;
    server_name *.example.com;
    # 通配符匹配
}

server {
    listen 80;
    server_name ~^www\.([0-9]+)\.example\.com$;
    # 正则匹配
}

server {
    listen 80 default_server;
    server_name _;
    # 默认服务器,捕获所有未匹配的请求
    return 444;  # 或返回自定义错误页
}

调试方法

# 查看实际处理的 server 块
curl -v -H “Host: example.com” http://<server-ip>/

# 检查配置加载顺序
nginx -T | grep -A 5 “server_name”

2.3 location 匹配优先级问题

问题现象

  • 某些 URL 被错误的 location 处理
  • 静态文件被当作动态请求处理

location 匹配规则

# 匹配优先级(从高到低):
# 1. = 精确匹配
# 2. ^~ 前缀匹配(不检查正则)
# 3. ~ 正则匹配(区分大小写)
# 4. ~* 正则匹配(不区分大小写)
# 5. 不带修饰符的前缀匹配

server {
    listen 80;
    server_name example.com;

    # 优先级 1:精确匹配
    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    # 优先级 2:前缀匹配(停止正则检查)
    location ^~ /static/ {
        alias /var/www/static/;
        expires 30d;
    }

    # 优先级 3:正则匹配
    location ~ \.(jpg|jpeg|png|gif|ico)$ {
        root /var/www/images;
        expires 7d;
    }

    location ~* \.(css|js)$ {
        root /var/www/assets;
        expires 1d;
    }

    # 优先级 5:通用前缀匹配
    location /api/ {
        proxy_pass http://backend;
    }

    # 优先级最低:根路径
    location / {
        try_files $uri $uri/ /index.html;
    }
}

调试技巧

# 测试不同 URL 的匹配结果
curl http://example.com/static/style.css
curl http://example.com/api/users
curl http://example.com/images/logo.png

# 开启调试日志
# nginx.conf
error_log /var/log/nginx/error.log debug;

2.4 root 与 alias 使用混淆

问题现象

  • 文件路径拼接错误
  • 404 Not Found

区别说明

# root: 将 location 路径拼接到 root 后面
# alias: 用 alias 路径替换 location 路径

location /images/ {
    root /var/www;
    # 请求 /images/logo.png → /var/www/images/logo.png
}

location /static/ {
    alias /var/www/assets/;
    # 请求 /static/style.css → /var/www/assets/style.css
    # 注意:alias 末尾的斜杠很重要
}

# ❌ 错误示例
location /static/ {
    alias /var/www/assets;  # 缺少末尾斜杠
    # 请求 /static/style.css → /var/www/assetsstyle.css (错误)
}

三、反向代理与负载均衡

3.1 后端服务连接失败

问题现象

# error.log
2024/03/09 10:30:45 [error] connect() failed (111: Connection refused)
2024/03/09 10:30:45 [error] upstream timed out (110: Connection timed out)

解决方案

upstream backend {
    server 127.0.0.1:8080;

    # 配置连接参数
    keepalive 32;          # 保持连接数
    keepalive_timeout 60s;
    keepalive_requests 100;
}

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://backend;

        # 超时设置
        proxy_connect_timeout 5s;
        proxy_send_timeout 30s;
        proxy_read_timeout 30s;

        # 重试机制
        proxy_next_upstream error timeout http_502 http_503 http_504;
        proxy_next_upstream_tries 3;
        proxy_next_upstream_timeout 10s;

        # 传递必要头部
        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_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
    }
}

3.2 负载均衡策略配置

问题现象

  • 后端服务器负载不均
  • 某些服务器过载

负载均衡策略

# 1. 轮询(默认)
upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

# 2. 加权轮询
upstream backend {
    server 192.168.1.10:8080 weight=3;  # 处理 3/6 的请求
    server 192.168.1.11:8080 weight=2;  # 处理 2/6 的请求
    server 192.168.1.12:8080 weight=1;  # 处理 1/6 的请求
}

# 3. IP Hash(会话保持)
upstream backend {
    ip_hash;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

# 4. 最少连接
upstream backend {
    least_conn;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

# 5. 公平调度(第三方模块)
upstream backend {
    fair;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

# 6. URL Hash(第三方模块)
upstream backend {
    hash $request_uri consistent;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

# 服务器状态标记
upstream backend {
    server 192.168.1.10:8080;              # 正常
    server 192.168.1.11:8080 backup;       # 备份服务器
    server 192.168.1.12:8080 down;         # 临时下线
    server 192.168.1.13:8080 max_fails=3 fail_timeout=30s;
}

3.3 WebSocket 代理配置

问题现象

  • WebSocket 连接建立后立即断开
  • 升级协议失败

解决方案

server {
    listen 80;
    server_name ws.example.com;

    location /ws/ {
        proxy_pass http://backend;

        # WebSocket 必需配置
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection “upgrade”;

        # 超时设置(WebSocket 长连接)
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;

        # 其他头部
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

3.4 获取客户端真实 IP

问题现象

  • 后端获取的 IP 是 Nginx 的 IP
  • 日志中记录的 IP 不正确

解决方案

# 1. Nginx 配置传递真实 IP
http {
    # 设置可信代理
    set_real_ip_from 10.0.0.0/8;
    set_real_ip_from 172.16.0.0/12;
    set_real_ip_from 192.168.0.0/16;
    set_real_ip_from 127.0.0.1;

    # 从哪个头部获取真实 IP
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;
}

# 2. 传递 IP 到后端
server {
    location / {
        proxy_pass http://backend;
        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_set_header X-Forwarded-Host $host;
    }
}

# 3. 后端应用获取 IP(以 Java 为例)
public String getClientIp(HttpServletRequest request) {
    String ip = request.getHeader(“X-Forwarded-For”);
    if (ip != null && !ip.isEmpty() && !“unknown”.equalsIgnoreCase(ip)) {
        // X-Forwarded-For 可能包含多个 IP,取第一个
        return ip.split(“,”)[0].trim();
    }
    return request.getHeader(“X-Real-IP”);
}

四、性能优化问题

4.1 静态文件性能优化

问题现象

  • 静态资源加载慢
  • 带宽占用高

解决方案

server {
    listen 80;
    server_name static.example.com;

    # 开启 sendfile
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    # 禁用访问日志(高并发静态文件)
    access_log off;

    # 静态文件配置
    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
        root /var/www/images;

        # 浏览器缓存
        expires 30d;
        add_header Cache-Control “public, immutable”;

        # 禁用日志
        access_log off;

        # 压缩(对已压缩文件无效)
        gzip_static off;
    }

    location ~* \.(css|js|html)$ {
        root /var/www/assets;

        # 浏览器缓存
        expires 7d;
        add_header Cache-Control “public”;

        # 开启 gzip
        gzip_static on;
    }

    # 开启 open_file_cache
    open_file_cache max=10000 inactive=30s;
    open_file_cache_valid 60s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;
}

4.2 Gzip 压缩配置

问题现象

  • 页面加载慢
  • 带宽消耗大

解决方案

http {
    # 开启 gzip
    gzip on;

    # 最小压缩文件大小
    gzip_min_length 1k;

    # 压缩级别(1-9,越高压缩率越大但 CPU 消耗越多)
    gzip_comp_level 5;

    # 压缩类型
    gzip_types text/plain
               text/css
               text/xml
               text/javascript
               application/json
               application/javascript
               application/xml
               application/xml+rss
               application/x-javascript;

    # 禁用 IE6 gzip
    gzip_disable “msie6”;

    # Vary 头(支持缓存)
    gzip_vary on;

    # 代理缓冲压缩
    gzip_proxied any;

    # 预压缩(需要安装 gzip-static 模块)
    # gzip_static on;
}

验证压缩效果

# 检查响应头
curl -H “Accept-Encoding: gzip” -I https://example.com/style.css

# 应该看到
# Content-Encoding: gzip
# Content-Length: <压缩后大小>

# 对比压缩前后
curl -H “Accept-Encoding: gzip” https://example.com/app.js | wc -c
curl https://example.com/app.js | wc -c

4.3 连接数优化

问题现象

# error.log
2024/03/09 10:30:45 [emerg] worker_connections are not enough

解决方案

# 查看系统限制
ulimit -n  # 文件描述符限制

# /etc/security/limits.conf 添加
nginx soft nofile 65535
nginx hard nofile 65535

# nginx.conf
user nginx;
worker_processes auto;

events {
    # 每个 worker 最大连接数
    worker_connections 65535;

    # 允许一个 worker 处理多个连接
    multi_accept on;

    # 使用 epoll(Linux)
    use epoll;
}

http {
    # keepalive 配置
    keepalive_timeout 65;
    keepalive_requests 1000;

    # 上游连接池
    upstream backend {
        server 127.0.0.1:8080;
        keepalive 32;
    }
}

4.4 缓冲与缓存优化

问题现象

  • 大文件上传失败
  • 响应慢

解决方案

http {
    # 客户端请求体缓冲
    client_body_buffer_size 16k;
    client_max_body_size 100m;  # 最大上传文件大小

    # 客户端请求头缓冲
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;

    # 代理缓冲
    proxy_buffering on;
    proxy_buffer_size 4k;
    proxy_buffers 8 16k;
    proxy_busy_buffers_size 24k;

    # 快速cgi 缓冲(PHP)
    fastcgi_buffering on;
    fastcgi_buffer_size 4k;
    fastcgi_buffers 8 16k;
    fastcgi_busy_buffers_size 24k;
}

五、SSL/HTTPS 问题

5.1 SSL 证书配置

问题现象

# error.log
SSL_do_handshake() failed
certificate verify failed

解决方案

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

    # 证书文件
    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

    # 证书链(可选,某些 CA 需要)
    # ssl_trusted_certificate /etc/nginx/ssl/chain.pem;

    # SSL 优化配置
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    # 现代加密配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # HSTS
    add_header Strict-Transport-Security “max-age=63072000” always;
}

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

证书检查

# 检查证书有效期
openssl x509 -in /etc/nginx/ssl/example.com.crt -noout -dates

# 检查证书链
openssl verify -CAfile /etc/nginx/ssl/chain.pem /etc/nginx/ssl/example.com.crt

# 在线检查
# https://www.ssllabs.com/ssltest/

5.2 混合内容问题

问题现象

  • 浏览器显示“不安全”
  • Console 警告:Mixed Content

解决方案

server {
    listen 443 ssl;
    server_name example.com;

    # 替换 HTTP 资源为 HTTPS
    sub_filter ‘http://’ ‘https://’;
    sub_filter_once off;
    sub_filter_types text/html application/json;

    # 内容安全策略
    add_header Content-Security-Policy “upgrade-insecure-requests” always;
}

前端修复

<!— ❌ 错误 —>
<script src=“http://cdn.example.com/jquery.js”></script>
<img src=“http://example.com/logo.png”>

<!— ✅ 正确 —>
<script src=“//cdn.example.com/jquery.js”></script>
<script src=“https://cdn.example.com/jquery.js”></script>
<img src=“/logo.png”>

5.3 多域名 SSL 配置

解决方案

# 1. 多证书配置
server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
}

server {
    listen 443 ssl;
    server_name api.example.com;
    ssl_certificate /etc/nginx/ssl/api.example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/api.example.com.key;
}

# 2. 通配符证书
server {
    listen 443 ssl;
    server_name *.example.com;
    ssl_certificate /etc/nginx/ssl/wildcard.example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/wildcard.example.com.key;
}

# 3. SAN 证书(多域名)
server {
    listen 443 ssl;
    server_name example.com www.example.com api.example.com;
    ssl_certificate /etc/nginx/ssl/san.crt;
    ssl_certificate_key /etc/nginx/ssl/san.key;
}

六、安全相关问题

6.1 防止常见攻击

解决方案

http {
    # 隐藏 Nginx 版本
    server_tokens off;

    # 限制请求头大小
    large_client_header_buffers 4 8k;

    # 限制请求体大小
    client_max_body_size 10m;

    # 限制请求方法
    if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE|OPTIONS)$) {
        return 405;
    }
}

server {
    # 防止点击劫持
    add_header X-Frame-Options “SAMEORIGIN” always;

    # 防止 MIME 类型嗅探
    add_header X-Content-Type-Options “nosniff” always;

    # XSS 防护
    add_header X-XSS-Protection “1; mode=block” always;

    # 内容安全策略
    add_header Content-Security-Policy “default-src ‘self’; script-src ‘self’ ‘unsafe-inline’; style-src ‘self’ ‘unsafe-inline’;” always;

    # 限制请求频率
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
    limit_req zone=one burst=20 nodelay;

    # 限制连接数
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    limit_conn addr 10;
}

6.2 IP 访问控制

解决方案

server {
    listen 80;
    server_name admin.example.com;

    # 允许特定 IP
    allow 192.168.1.0/24;
    allow 10.0.0.100;

    # 拒绝其他所有
    deny all;

    location / {
        # ...
    }
}

# 地理位置限制(需要 GeoIP 模块)
http {
    geoip_country /usr/share/GeoIP/GeoIP.dat;

    map $geoip_country_code $allowed_country {
        default no;
        CN yes;
        US yes;
    }

    server {
        if ($allowed_country = no) {
            return 403;
        }
    }
}

6.3 DDoS 防护

解决方案

http {
    # 限制请求速率
    limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
    limit_req_zone $server_name zone=server_limit:10m rate=50r/s;

    # 限制连接数
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

    # 超时设置
    client_body_timeout 10s;
    client_header_timeout 10s;
    keepalive_timeout 65s;
    send_timeout 10s;
}

server {
    listen 80;

    # 应用限制
    limit_req zone=req_limit burst=20 nodelay;
    limit_conn conn_limit 10;

    # 异常 UA 拦截
    if ($http_user_agent ~* (wget|curl|scan|bot)) {
        return 403;
    }

    # 空 UA 拦截
    if ($http_user_agent = “”) {
        return 403;
    }
}

七、日志与故障排查

7.1 日志配置

解决方案

http {
    # 自定义日志格式
    log_format main ‘$remote_addr - $remote_user [$time_local] “$request” ‘
                    ‘$status $body_bytes_sent “$http_referer” ‘
                    ‘“$http_user_agent” “$http_x_forwarded_for” ‘
                    ‘rt=$request_time uct=“$upstream_connect_time” ‘
                    ‘uht=“$upstream_header_time” urt=“$upstream_response_time”’;

    log_format json escape=json ‘{“time”:“$time_iso8601”,’
                                    ‘“remote_addr”:“$remote_addr”,’
                                    ‘“method”:“$request_method”,’
                                    ‘“uri”:“$request_uri”,’
                                    ‘“status”:$status,’
                                    ‘“bytes”:$body_bytes_sent,’
                                    ‘“referer”:“$http_referer”,’
                                    ‘“ua”:“$http_user_agent”,’
                                    ‘“request_time”:$request_time}’;

    # 访问日志
    access_log /var/log/nginx/access.log main;

    # 错误日志(级别:debug | info | notice | warn | error | crit | alert | emerg)
    error_log /var/log/nginx/error.log warn;

    # 按域名分割日志
    # server 块中
    access_log /var/log/nginx/example.com.access.log main;
    error_log /var/log/nginx/example.com.error.log warn;
}

7.2 日志分析

常用分析命令

# 1. 访问量 Top 10 IP
awk ‘{print $1}’ /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10

# 2. 访问量 Top 10 URL
awk ‘{print $7}’ /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10

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

# 4. 404 错误分析
grep “ 404 “ /var/log/nginx/access.log | awk ‘{print $7}’ | sort | uniq -c | sort -rn

# 5. 慢请求分析(请求时间>1s)
awk ‘($NF > 1) {print $7, $NF}’ /var/log/nginx/access.log | sort -k2 -rn | head -20

# 6. 实时日志监控
tail -f /var/log/nginx/access.log

# 7. 错误日志实时监控
tail -f /var/log/nginx/error.log

# 8. 使用 goaccess 可视化分析
goaccess /var/log/nginx/access.log -o report.html —log-format=COMBINED

7.3 故障排查流程

排查步骤

# 1. 检查 Nginx 状态
systemctl status nginx
ps aux | grep nginx

# 2. 测试配置
nginx -t

# 3. 查看错误日志
tail -100 /var/log/nginx/error.log

# 4. 检查端口监听
netstat -tlnp | grep nginx
ss -tlnp | grep nginx

# 5. 检查连接数
netstat -an | grep :80 | wc -l

# 6. 检查系统资源
top
free -h
df -h

# 7. 测试响应
curl -v http://localhost/
curl -I http://localhost/

# 8. 检查 upstream 状态
# 需要配置 status 模块
location /nginx_status {
    stub_status on;
    allow 127.0.0.1;
    deny all;
}
curl http://localhost/nginx_status

常见错误码排查

错误码 含义 排查方向
400 错误请求 检查请求格式、URL 编码
401 未授权 检查认证配置
403 禁止访问 检查权限、IP 限制
404 未找到 检查文件路径、location 配置
405 方法不允许 检查请求方法限制
413 请求体过大 检查 client_max_body_size
414 URL 过长 检查 large_client_header_buffers
499 客户端断开 检查后端响应时间
500 服务器错误 检查错误日志
502 错误网关 检查 upstream 服务状态
503 服务不可用 检查后端服务、限流配置
504 网关超时 检查 proxy_read_timeout

八、实际案例场景

案例一:API 网关配置

场景描述
公司微服务架构,需要 Nginx 作为 API 网关,实现反向代理负载均衡、路由转发、限流、认证等功能。

解决方案

# API 网关配置
upstream user_service {
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    keepalive 32;
}

upstream order_service {
    server 10.0.2.10:8080;
    server 10.0.2.11:8080;
    keepalive 32;
}

upstream payment_service {
    server 10.0.3.10:8080;
    server 10.0.3.11:8080;
    keepalive 32;
}

# 限流区域
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;
limit_req_zone $server_name zone=service_limit:10m rate=1000r/s;

server {
    listen 80;
    server_name api.example.com;

    # 访问日志
    access_log /var/log/nginx/api.access.log json;
    error_log /var/log/nginx/api.error.log warn;

    # 通用安全头
    add_header X-Frame-Options “DENY” always;
    add_header X-Content-Type-Options “nosniff” always;

    # 健康检查
    location /health {
        access_log off;
        return 200 “OK\n”;
        add_header Content-Type text/plain;
    }

    # 用户服务
    location /api/v1/users/ {
        limit_req zone=api_limit burst=50 nodelay;

        proxy_pass http://user_service;
        proxy_http_version 1.1;
        proxy_set_header Connection “”;
        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_connect_timeout 3s;
        proxy_read_timeout 10s;
        proxy_send_timeout 10s;
    }

    # 订单服务
    location /api/v1/orders/ {
        limit_req zone=api_limit burst=30 nodelay;

        proxy_pass http://order_service;
        proxy_http_version 1.1;
        proxy_set_header Connection “”;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;

        # 重试配置
        proxy_next_upstream error timeout http_502 http_503;
        proxy_next_upstream_tries 2;
    }

    # 支付服务(需要认证)
    location /api/v1/payments/ {
        # JWT 验证(需要 auth_request 模块)
        auth_request /auth/validate;

        limit_req zone=api_limit burst=10 nodelay;

        proxy_pass http://payment_service;
        proxy_http_version 1.1;
        proxy_set_header Connection “”;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 认证子请求
    location = /auth/validate {
        internal;
        proxy_pass http://auth_service/validate;
        proxy_http_version 1.1;
        proxy_set_header Authorization $http_authorization;
        proxy_pass_request_body off;
        proxy_set_header Content-Length “”;
        proxy_set_header X-Original-URI $request_uri;
    }
}

案例二:动静分离配置

场景描述
电商网站,需要分离静态资源和动态请求,优化访问速度。

解决方案

upstream app_servers {
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
}

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

    root /var/www/html;
    index index.html index.htm;

    # Gzip 压缩
    gzip on;
    gzip_min_length 1k;
    gzip_comp_level 5;
    gzip_types text/plain text/css application/json application/javascript;

    # 静态文件缓存配置
    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp|woff|woff2|ttf|eot)$ {
        root /var/www/static;
        expires 30d;
        add_header Cache-Control “public, immutable”;
        access_log off;

        # 防盗链
        valid_referers none blocked server_names *.example.com example.com;
        if ($invalid_referer) {
            return 403;
        }
    }

    location ~* \.(css|js)$ {
        root /var/www/static;
        expires 7d;
        add_header Cache-Control “public”;
        gzip_static on;
    }

    # HTML 不缓存
    location ~* \.html$ {
        root /var/www/html;
        expires -1;
        add_header Cache-Control “no-cache, no-store, must-revalidate”;
    }

    # 动态请求代理
    location / {
        try_files $uri $uri/ @backend;
    }

    location @backend {
        proxy_pass http://app_servers;
        proxy_http_version 1.1;
        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_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 16k;

        # 超时
        proxy_connect_timeout 5s;
        proxy_read_timeout 30s;
    }

    # 上传文件
    location /upload/ {
        client_max_body_size 50m;
        client_body_buffer_size 128k;

        proxy_pass http://app_servers;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

案例三:HTTPS 全站加密

场景描述
企业官网需要全站 HTTPS,包括 HTTP 自动跳转、HSTS、证书自动更新。

解决方案

# HTTP 服务器 - 强制跳转 HTTPS
server {
    listen 80;
    server_name www.example.com example.com;

    # ACME 挑战(Let’s Encrypt)
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    # 其他所有请求跳转 HTTPS
    location / {
        return 301 https://$host$request_uri;
    }
}

# HTTPS 服务器
server {
    listen 443 ssl http2;
    server_name www.example.com example.com;

    root /var/www/html;
    index index.html;

    # SSL 证书
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

    # SSL 优化
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;

    # 安全头
    add_header Strict-Transport-Security “max-age=63072000; includeSubDomains; preload” always;
    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 Content-Security-Policy “default-src ‘self’; script-src ‘self’ ‘unsafe-inline’ ‘unsafe-eval’ https://cdn.example.com; style-src ‘self’ ‘unsafe-inline’ https://fonts.googleapis.com; font-src ‘self’ https://fonts.gstatic.com; img-src ‘self’ data: https:; connect-src ‘self’ https://api.example.com;” always;

    # 静态资源
    location /static/ {
        alias /var/www/static/;
        expires 30d;
        add_header Cache-Control “public, immutable”;
    }

    # 动态请求
    location / {
        try_files $uri $uri/ /index.html;
    }
}

证书自动更新脚本

#!/bin/bash
# /usr/local/bin/certbot-renew.sh

# 更新证书
certbot renew —quiet

# 检查 Nginx 配置
nginx -t

# 重载 Nginx
if [ $? -eq 0 ]; then
    systemctl reload nginx
    echo “Nginx reloaded successfully”
else
    echo “Nginx config test failed”
    exit 1
fi

定时任务

# crontab -e
# 每天凌晨 2 点检查证书更新
0 2 * * * /usr/local/bin/certbot-renew.sh >> /var/log/certbot-renew.log 2>&1

案例四:高并发直播流媒体

场景描述
直播平台,需要处理高并发 HTTP-FLV/HLS 流媒体分发。

解决方案

# 需要安装 nginx-rtmp-module

user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;

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

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

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    keepalive_timeout 65;
    keepalive_requests 1000;

    # 访问日志
    log_format main ‘$remote_addr - [$time_local] “$request” ‘
                    ‘$status $bytes_sent “$http_referer” ‘
                    ‘“$http_user_agent” $request_time’;

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

    server {
        listen 80;
        server_name live.example.com;

        access_log /var/log/nginx/live.access.log main;
        error_log /var/log/nginx/live.error.log warn;

        # HLS 分发
        location /hls/ {
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }

            root /var/www/stream;

            # 防止盗链
            valid_referers none blocked server_names *.example.com example.com;
            if ($invalid_referer) {
                return 403;
            }

            # 缓存配置
            add_header Cache-Control “max-age=60”;
            expires 1m;
        }

        # FLV 流
        location /live/ {
            proxy_pass http://127.0.0.1:8080;
            proxy_http_version 1.1;
            proxy_set_header Connection “”;
            proxy_buffering off;
            proxy_cache off;
            proxy_redirect off;

            # 超时设置(长连接)
            proxy_read_timeout 86400s;
            proxy_send_timeout 86400s;
        }

        # 统计信息
        location /stats {
            stub_status on;
            allow 127.0.0.1;
            allow 10.0.0.0/8;
            deny all;
        }
    }
}

# RTMP 配置
rtmp {
    server {
        listen 1935;
        chunk_size 4096;

        # 直播应用
        application live {
            live on;
            record off;

            # HLS
            hls on;
            hls_path /var/www/stream/hls;
            hls_fragment 5s;
            hls_playlist_length 15s;

            # 限制
            max_connections 1000;

            # 推流认证
            on_publish http://127.0.0.1:8080/auth/publish;
            on_play http://127.0.0.1:8080/auth/play;
        }

        # 录制应用
        application record {
            live on;
            record all;
            record_path /var/www/stream/record;
            record_unique on;
        }
    }
}

附录:常用命令速查

# 配置测试
nginx -t
nginx -T

# 启动/停止/重启
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
systemctl reload nginx  # 平滑重载

# 查看状态
systemctl status nginx
ps aux | grep nginx

# 查看监听端口
netstat -tlnp | grep nginx
ss -tlnp | grep nginx

# 日志操作
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log
grep “404” /var/log/nginx/access.log

# 平滑升级
nginx -s upgrade

# 查看编译参数
nginx -V

结语

Nginx 作为高性能的 Web 服务器和反向代理,在生产环境中扮演着重要角色。掌握常见问题的排查方法和解决方案,能够帮助我们:

  1. 快速定位问题:通过日志和状态码快速找到问题根源
  2. 合理配置优化:根据业务场景调整配置参数,进行有效的性能优化
  3. 保障系统稳定:通过限流、超时等机制保护后端服务
  4. 提升访问体验:通过缓存、压缩等手段加速页面加载

希望这份指南能帮助你在实际工作中更好地使用 Nginx,遇到问题时能够快速找到解决方案。如果你有更多的 Nginx 使用心得或问题,欢迎在云栈社区与更多开发者交流讨论。

参考资料

  • Nginx 官方文档
  • Nginx 配置最佳实践
  • Mozilla SSL 配置生成器
  • Nginx 性能优化指南



上一篇:Kubernetes Ingress从入门到精通:路由、TLS、安全与生产最佳实践
下一篇:谷歌AI模式自引数据揭秘:SEO与行业生态影响分析
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-10 08:52 , Processed in 0.543918 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表