Nginx 教程

纯干货教学,从零开始学习 Nginx

Nginx 故障排查

掌握 Nginx 服务器故障排查的方法和技巧

故障排查流程

当 Nginx 出现故障时,建议按照以下流程进行排查:

  1. 检查 Nginx 服务状态 - 确认 Nginx 是否正常运行
  2. 查看错误日志 - 分析 Nginx 错误日志,定位问题原因
  3. 检查配置文件 - 验证 Nginx 配置文件语法是否正确
  4. 测试网络连接 - 确认网络连接和端口是否正常
  5. 分析访问日志 - 查看访问日志,了解请求情况
  6. 测试配置变更 - 逐步测试配置变更,找出问题所在
  7. 重启服务 - 在必要时重启 Nginx 服务

检查 Nginx 服务状态

查看服务状态

# 使用 systemctl(Systemd)
sudo systemctl status nginx

# 使用 service(SysV)
sudo service nginx status

# 检查进程
ps aux | grep nginx

# 检查端口
netstat -tuln | grep nginx
ss -tuln | grep nginx

启动和重启服务

# 启动服务
sudo systemctl start nginx  # Systemd
sudo service nginx start    # SysV

# 重启服务
sudo systemctl restart nginx  # Systemd
sudo service nginx restart    # SysV

# 重新加载配置
sudo systemctl reload nginx  # Systemd
sudo service nginx reload    # SysV

# 使用 nginx 命令重新加载
nginx -s reload

查看 Nginx 日志

错误日志

# 查看错误日志
cat /var/log/nginx/error.log

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

# 查看最近的错误
tail -n 50 /var/log/nginx/error.log

# 搜索特定错误
grep "error" /var/log/nginx/error.log
grep "warn" /var/log/nginx/error.log

访问日志

# 查看访问日志
cat /var/log/nginx/access.log

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

# 查看最近的访问
tail -n 50 /var/log/nginx/access.log

# 搜索特定请求
grep "GET /api" /var/log/nginx/access.log
grep "404" /var/log/nginx/access.log

检查 Nginx 配置

测试配置语法

# 测试配置语法
nginx -t

# 测试特定配置文件
nginx -t -c /etc/nginx/nginx.conf

查看配置文件

# 查看主配置文件
cat /etc/nginx/nginx.conf

# 查看站点配置文件
ls -la /etc/nginx/conf.d/
cat /etc/nginx/conf.d/default.conf

# 查看所有配置文件
find /etc/nginx -name "*.conf" -exec cat {} \;

常见故障及解决方案

配置语法错误

症状:Nginx 无法启动或重新加载配置

解决方案

  1. 使用 nginx -t 检查配置语法
  2. 修复错误提示中指出的语法问题
  3. 重新加载配置:nginx -s reload

端口被占用

症状:Nginx 启动失败,错误信息显示端口已被占用

解决方案

  1. 查找占用端口的进程:lsof -i :80netstat -tuln | grep :80
  2. 终止占用端口的进程:kill -9 [PID]
  3. 或修改 Nginx 配置,使用不同的端口
  4. 重启 Nginx 服务

403 Forbidden 错误

症状:访问网站时返回 403 Forbidden 错误

解决方案

  1. 检查文件权限:ls -la /var/www/html
  2. 设置正确的文件权限:chown -R nginx:nginx /var/www/html
  3. 检查 Nginx 配置中的访问控制规则
  4. 检查 SELinux 或 AppArmor 配置
  5. 检查目录索引设置:确保 index 指令包含正确的索引文件
  6. 检查 location 指令中的 deny 规则

404 Not Found 错误

症状:访问网站时返回 404 Not Found 错误

解决方案

  1. 确认文件是否存在:ls -la /var/www/html/path/to/file
  2. 检查 Nginx 配置中的 root 或 alias 指令
  3. 检查 location 配置是否正确
  4. 检查 rewrite 规则是否正确
  5. 检查 try_files 指令配置:
    location / {
        try_files $uri $uri/ =404;
    }
  6. 检查服务器名称和端口配置

502 Bad Gateway 错误

症状:访问网站时返回 502 Bad Gateway 错误

解决方案

  1. 检查后端服务器是否正常运行:systemctl status backend-service
  2. 检查 Nginx 配置中的 proxy_pass 指令是否正确
  3. 检查后端服务器端口是否正确:netstat -tuln | grep backend-port
  4. 检查网络连接是否正常:ping backend-servertelnet backend-server backend-port
  5. 检查后端服务器防火墙设置
  6. 检查 proxy_set_header 指令是否正确设置

503 Service Unavailable 错误

症状:访问网站时返回 503 Service Unavailable 错误

解决方案

  1. 检查后端服务器是否正常运行
  2. 检查 Nginx 配置中的 upstream 配置是否正确
  3. 检查负载均衡配置是否正确
  4. 检查服务器资源使用情况:tophtop
  5. 检查 upstream 服务器的健康检查配置:
    upstream backend {
        server backend1.example.com max_fails=3 fail_timeout=30s;
        server backend2.example.com max_fails=3 fail_timeout=30s;
    }
  6. 检查是否启用了维护模式或限流

504 Gateway Timeout 错误

症状:访问网站时返回 504 Gateway Timeout 错误

解决方案

  1. 检查后端服务器响应时间:curl -o /dev/null -s -w "%{time_total}\n" http://backend-server
  2. 调整 Nginx 代理超时设置:
    proxy_connect_timeout 60;
    proxy_send_timeout 60;
    proxy_read_timeout 60;
    proxy_buffer_size 16k;
    proxy_buffers 4 64k;
    proxy_busy_buffers_size 128k;
  3. 优化后端服务器性能
  4. 检查网络连接是否正常
  5. 考虑使用异步处理或队列系统处理长时间运行的请求

400 Bad Request 错误

症状:访问网站时返回 400 Bad Request 错误

解决方案

  1. 检查请求 URL 是否正确
  2. 检查请求头是否正确
  3. 检查 Nginx 配置中的 client_max_body_size 设置
  4. 检查是否有无效的请求参数

401 Unauthorized 错误

症状:访问网站时返回 401 Unauthorized 错误

解决方案

  1. 检查认证配置是否正确
  2. 确认用户名和密码是否正确
  3. 检查 auth_basic 指令配置

405 Method Not Allowed 错误

症状:访问网站时返回 405 Method Not Allowed 错误

解决方案

  1. 检查请求方法是否被允许
  2. 检查 Nginx 配置中的 limit_except 指令
  3. 检查后端服务器是否支持该请求方法

413 Request Entity Too Large 错误

症状:上传文件时返回 413 Request Entity Too Large 错误

解决方案

  1. 调整 Nginx 配置中的 client_max_body_size 设置:
    http {
        client_max_body_size 10M;  # 允许最大 10MB 的请求体
    }
    
  2. 同时调整后端服务器的相关设置

500 Internal Server Error 错误

症状:访问网站时返回 500 Internal Server Error 错误

解决方案

  1. 查看 Nginx 错误日志:tail -n 50 /var/log/nginx/error.log
  2. 检查后端应用是否正常运行
  3. 检查后端应用日志
  4. 检查 Nginx 配置中的 fastcgi_pass 或 proxy_pass 指令
  5. 检查文件权限和路径

性能相关问题

服务器响应缓慢

症状:网站加载速度慢,响应时间长

解决方案

  1. 检查服务器资源使用情况:topfree -mdf -h
  2. 优化 Nginx 配置,增加工作进程数和连接数:
    worker_processes auto;  # 自动设置为 CPU 核心数
    worker_rlimit_nofile 65536;
    
    events {
        worker_connections 10240;
        use epoll;
        multi_accept on;
    }
  3. 启用缓存和压缩:
    http {
        # 启用 gzip 压缩
        gzip on;
        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
        gzip_comp_level 6;
        gzip_min_length 256;
        gzip_buffers 16 8k;
        
        # 启用浏览器缓存
        location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
            expires 30d;
            add_header Cache-Control "public, max-age=2592000";
        }
    }
  4. 优化后端应用性能
  5. 考虑使用 CDN 加速静态资源
  6. 使用 nginx-extras 或 OpenResty 提供更多优化功能
  7. 监控并优化数据库查询性能
  8. 使用缓存系统如 Redis 或 Memcached

连接数过多

症状:Nginx 连接数达到上限,新连接被拒绝

解决方案

  1. 增加 Nginx 连接数限制:
    events {
        worker_connections 10240;
    }
  2. 增加系统文件描述符限制:
    # 在 /etc/security/limits.conf 中添加
    nginx soft nofile 65536
    nginx hard nofile 65536
    
    # 在 /etc/sysctl.conf 中添加
    fs.file-max = 65536
    net.core.somaxconn = 4096
    
    # 应用系统配置
    sysctl -p
  3. 启用连接限制,防止 DoS 攻击:
    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
    
    location / {
        limit_req zone=mylimit burst=20 nodelay;
    }
  4. 调整 keepalive 设置:
    keepalive_timeout 65;
    keepalive_requests 100;

内存使用过高

症状:Nginx 进程占用内存过高,导致服务器内存不足

解决方案

  1. 检查 Nginx 工作进程数:避免设置过多工作进程
  2. 调整 worker_rlimit_nofile 设置
  3. 检查是否有内存泄漏的模块
  4. 优化缓存设置:减少缓存大小
  5. 使用 ps aux --sort=-%mem | grep nginx 查看内存使用情况

CPU 使用率过高

症状:Nginx 进程占用 CPU 过高,导致服务器响应缓慢

解决方案

  1. 检查是否有大量并发连接或请求
  2. 优化 Nginx 配置:调整 worker_processes 和 worker_connections
  3. 检查是否有复杂的正则表达式或重写规则
  4. 启用 gzip_static 模块,减少 CPU 压缩开销
  5. 使用 top -H -p [nginx-pid] 查看具体线程 CPU 使用情况

SSL/TLS 相关问题

SSL 证书错误

症状:浏览器显示 SSL 证书错误

解决方案

  1. 检查 SSL 证书是否过期:openssl x509 -in server.crt -dates -noout
  2. 确认证书配置正确:检查 ssl_certificate 和 ssl_certificate_key 指令是否指向正确的文件路径
  3. 验证证书链是否完整:使用 openssl verify -CAfile ca-bundle.crt server.crt
  4. 检查证书文件权限:确保 Nginx 进程可以读取证书文件
  5. 如果使用自签名证书,考虑使用 Let's Encrypt 获取免费证书
  6. 检查证书域名是否匹配:确保证书包含当前访问的域名

HTTPS 连接失败

症状:无法建立 HTTPS 连接

解决方案

  1. 检查 443 端口是否开放:netstat -tuln | grep 443
  2. 检查防火墙配置,确保 443 端口已开放:
    # 检查防火墙状态
    firewall-cmd --state
    
    # 开放 443 端口
    firewall-cmd --permanent --add-port=443/tcp
    
    # 重新加载防火墙配置
    firewall-cmd --reload
  3. 检查 SSL 配置是否正确:确保 ssl_protocols 和 ssl_ciphers 配置合理
  4. 查看 Nginx 错误日志,了解具体错误原因:tail -n 50 /var/log/nginx/error.log
  5. 测试 SSL 连接:使用 openssl s_client -connect example.com:443

SSL 握手失败

症状:SSL 握手过程失败,无法建立安全连接

解决方案

  1. 检查 SSL 协议版本配置:确保支持客户端使用的 SSL/TLS 版本
  2. 检查密码套件配置:确保配置了客户端支持的密码套件
  3. 检查证书是否被客户端信任
  4. 使用 openssl s_client -connect example.com:443 -debug 查看详细握手过程

SSL 会话重用失败

症状:SSL 会话无法重用,每次连接都需要重新握手

解决方案

  1. 启用 SSL 会话缓存:
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
  2. 检查 SSL 会话票证配置:
    ssl_session_tickets on;

Let's Encrypt 证书自动续期失败

症状:Let's Encrypt 证书无法自动续期,导致证书过期

解决方案

  1. 检查 crontab 配置:确保续期脚本已正确设置
  2. 手动运行续期命令:certbot renew --dry-run
  3. 检查域名解析是否正确:确保域名可以正常解析到服务器
  4. 检查防火墙设置:确保 80 端口可以正常访问(用于 HTTP-01 挑战)
  5. 查看续期日志:tail -n 50 /var/log/letsencrypt/letsencrypt.log

高级故障排查

使用 strace 跟踪系统调用

# 跟踪 Nginx 进程
sudo strace -p [Nginx PID]

# 启动 Nginx 并跟踪
sudo strace -f nginx

# 跟踪特定系统调用
sudo strace -e open,read,write -p [Nginx PID]

# 输出到文件
sudo strace -o nginx.strace -p [Nginx PID]

使用 gdb 调试 Nginx

# 安装 gdb
sudo apt install gdb  # Ubuntu/Debian
sudo yum install gdb  # CentOS/RHEL

# 调试 Nginx 进程
sudo gdb -p [Nginx PID]

# 查看堆栈跟踪
(gdb) bt

# 查看变量值
(gdb) print variable_name

# 设置断点
(gdb) break function_name

# 继续执行
(gdb) continue

# 单步执行
(gdb) step
(gdb) next

使用 tcpdump 抓包

# 安装 tcpdump
sudo apt install tcpdump  # Ubuntu/Debian
sudo yum install tcpdump  # CentOS/RHEL

# 抓取 80 端口的流量
sudo tcpdump -i eth0 port 80 -w nginx.pcap

# 抓取 443 端口的 HTTPS 流量
sudo tcpdump -i eth0 port 443 -w nginx-ssl.pcap

# 抓取特定 IP 的流量
sudo tcpdump -i eth0 host 192.168.1.100 -w client.pcap

# 分析抓包文件
wireshark nginx.pcap

# 简单分析
sudo tcpdump -r nginx.pcap | head -n 50

使用 nginx-debug 调试

# 安装 nginx-debug 包(如果可用)
sudo apt install nginx-debug  # Ubuntu/Debian

# 启动调试模式
sudo nginx-debug

# 查看详细日志
tail -f /var/log/nginx/error.log

使用 lsof 查看文件描述符

# 查看 Nginx 打开的文件
sudo lsof -p [Nginx PID]

# 查看 Nginx 监听的端口
sudo lsof -i -P -n | grep nginx

# 查看所有打开的日志文件
sudo lsof | grep nginx | grep log

使用 netstat 或 ss 查看网络连接

# 查看 Nginx 网络连接
netstat -tuln | grep nginx
ss -tuln | grep nginx

# 查看所有连接状态
netstat -ant | grep ESTABLISHED | grep nginx
ss -ant | grep ESTAB | grep nginx

# 查看连接统计
netstat -s | grep -E "connections|accepts|refused"
ss -s

使用 htop 监控系统资源

# 安装 htop
sudo apt install htop  # Ubuntu/Debian
sudo yum install htop  # CentOS/RHEL

# 运行 htop
htop

# 按 P 按 CPU 使用率排序
# 按 M 按内存使用率排序
# 按 T 按运行时间排序

使用 perf 分析性能

# 安装 perf
sudo apt install linux-tools-common  # Ubuntu/Debian
sudo yum install perf  # CentOS/RHEL

# 分析 Nginx 进程性能
sudo perf record -p [Nginx PID]

# 查看性能报告
sudo perf report

# 快速分析
sudo perf top -p [Nginx PID]

实践练习

练习1:基本故障排查

  1. 故意修改 Nginx 配置文件,引入语法错误
  2. 使用 nginx -t 检查配置错误
  3. 修复配置错误
  4. 重新加载配置并验证服务正常运行

练习2:处理 403 Forbidden 错误

  1. 创建一个测试文件:echo "Test" > /var/www/html/test.txt
  2. 设置错误的文件权限:chmod 600 /var/www/html/test.txt
  3. 尝试访问该文件,应该会收到 403 错误
  4. 查看 Nginx 错误日志,确认错误原因
  5. 修复文件权限:chmod 644 /var/www/html/test.txt
  6. 再次访问该文件,应该可以正常访问

练习3:处理 502 Bad Gateway 错误

  1. 配置 Nginx 反向代理到一个不存在的后端服务:
    location /api {
        proxy_pass http://localhost:9999;
    }
  2. 重新加载 Nginx 配置
  3. 尝试访问 /api 路径,应该会收到 502 错误
  4. 查看 Nginx 错误日志,确认错误原因
  5. 修复配置,指向正确的后端服务
  6. 再次访问,应该可以正常访问

常见问题解答

Q: Nginx 服务无法启动怎么办?

A: 按照以下步骤排查:

  1. 检查服务状态:sudo systemctl status nginx
  2. 查看错误日志:tail -n 50 /var/log/nginx/error.log
  3. 测试配置语法:nginx -t
  4. 检查端口是否被占用:netstat -tuln | grep :80
  5. 尝试手动启动并查看详细错误:nginx -g 'daemon off;'

Q: 如何查看 Nginx 版本信息?

A: 使用以下命令:

nginx -v      # 查看版本号
nginx -V      # 查看版本号和编译参数

Q: 如何查看 Nginx 正在使用的配置文件?

A: 使用以下命令:

nginx -t       # 会显示配置文件路径
ps aux | grep nginx  # 查看启动命令中的配置文件路径

Q: 如何备份和恢复 Nginx 配置?

A: 备份配置:

sudo tar -czf nginx-config-backup-$(date +%Y%m%d).tar.gz /etc/nginx/

恢复配置:

sudo tar -xzf nginx-config-backup-20240101.tar.gz -C /