一、为什么Nginx反向代理总让人头疼

搞过Web服务的同学都知道,Nginx反向代理就像个脾气古怪的门卫。配置对了,流量畅通无阻;配错了,要么直接给你吃闭门羹,要么把客人带到错误的地方。最常见的就是看到502 Bad Gateway、404 Not Found这些让人血压升高的错误页面。

我见过太多工程师在这种情况下的标准操作:先重启Nginx,不行就重启服务器,再不行就重装Nginx。这种"重启治百病"的做法虽然偶尔能蒙对,但根本问题还是没解决。今天咱们就来聊聊怎么科学地给Nginx反向代理"看病"。

二、基础检查:先排除低级错误

2.1 配置文件语法检查

每次修改完配置,第一件事应该是检查语法:

nginx -t
# 这个命令会检查配置文件语法是否正确
# 如果看到"successful"字样,至少说明语法没问题
# 如果报错,会明确告诉你哪行有问题

2.2 端口占用情况

有时候问题很简单,就是端口被占用了:

netstat -tulnp | grep :80
# 查看80端口是否被其他进程占用
# 如果看到除了Nginx之外的进程,那就是冲突了

2.3 最简单的反向代理配置示例

先看个最基本的正确配置长啥样(假设我们要代理到本地的8080端口):

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
# 这个配置做了三件事:
# 1. 监听80端口
# 2. 将所有请求转发到本机8080端口
# 3. 设置了必要的请求头

三、高级排错:当基础检查都通过时

3.1 查看Nginx错误日志

Nginx的错误日志通常在这里:

tail -f /var/log/nginx/error.log
# 实时查看错误日志
# 常见错误有:连接被拒绝、权限问题、超时等

3.2 检查上游服务状态

有时候不是Nginx的问题,而是后端服务挂了:

curl -v http://localhost:8080
# 直接测试后端服务是否正常响应
# -v参数可以看到详细的请求过程

3.3 超时问题排查

如果遇到504 Gateway Timeout,可能是后端响应太慢:

location / {
    proxy_pass http://backend;
    proxy_connect_timeout 5s;
    proxy_read_timeout 30s;
    proxy_send_timeout 30s;
}
# 这里设置了:
# 连接超时5秒
# 读取响应超时30秒
# 发送请求超时30秒

四、常见配置错误案例集锦

4.1 结尾斜杠引发的血案

location /api {
    proxy_pass http://localhost:8080;
}
# 这样配置的话,请求/api/user会被转发到http://localhost:8080/user

location /api {
    proxy_pass http://localhost:8080/;
}
# 这样配置的话,请求/api/user会被转发到http://localhost:8080//user
# 注意多了一个斜杠,可能导致404

4.2 头信息丢失问题

location / {
    proxy_pass http://localhost:8080;
    # 忘记设置Host头,可能导致后端服务无法识别域名
    # 正确的做法是加上:
    proxy_set_header Host $host;
}

4.3 WebSocket代理配置

location /ws {
    proxy_pass http://localhost:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}
# WebSocket需要特殊配置:
# 1. 使用HTTP/1.1协议
# 2. 设置Upgrade头
# 3. 设置Connection头

五、性能调优相关配置

5.1 连接池配置

upstream backend {
    server localhost:8080;
    keepalive 32;  # 保持的连接数
}

server {
    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}
# 使用连接池可以显著提升性能
# 注意要清空Connection头

5.2 缓冲区配置

location / {
    proxy_pass http://localhost:8080;
    proxy_buffer_size 16k;
    proxy_buffers 4 32k;
    proxy_busy_buffers_size 64k;
}
# 这些配置控制了:
# 单个缓冲区大小16k
# 4个32k的缓冲区
# 忙碌时缓冲区大小64k

六、特殊场景处理

6.1 处理重定向问题

location /app {
    proxy_pass http://localhost:8080;
    proxy_redirect http://localhost:8080/ https://example.com/app/;
}
# 当后端返回重定向时,Nginx可以修改重定向地址
# 这在前后端分离部署时特别有用

6.2 静态文件和动态请求分离

location / {
    try_files $uri @backend;
}

location @backend {
    proxy_pass http://localhost:8080;
}
# 先尝试找静态文件,找不到再转发到后端
# 这样可以减轻后端压力

七、终极武器:OpenResty动态调试

如果你用的是OpenResty,可以直接用Lua代码调试:

location / {
    access_by_lua_block {
        ngx.log(ngx.ERR, "请求头:", ngx.req.raw_header())
    }
    proxy_pass http://localhost:8080;
}
# 这样可以在错误日志中打印原始请求头
# 对于复杂问题排查非常有用

八、总结与最佳实践

经过这么多案例,我们可以总结出几个黄金法则:

  1. 每次修改配置后都要用nginx -t检查语法
  2. 遇到问题第一时间查看错误日志
  3. 复杂配置要拆解测试,先实现基本功能再添加高级特性
  4. 注意proxy_pass结尾斜杠的区别
  5. WebSocket需要特殊配置
  6. 生产环境一定要配置合理的超时时间
  7. 性能调优要从连接池和缓冲区着手

记住,Nginx反向代理就像个尽职的邮差,你得告诉它准确的投递地址和注意事项。配置时要站在Nginx的角度思考:它需要知道哪些信息才能正确转发请求?

最后送大家一个完整的参考配置:

server {
    listen 80;
    server_name example.com;
    
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    
    location / {
        proxy_pass http://localhost:8080/;
        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 5s;
        proxy_read_timeout 30s;
        proxy_send_timeout 30s;
        
        proxy_buffer_size 16k;
        proxy_buffers 4 32k;
    }
    
    location /ws {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

这个配置涵盖了大多数常见需求,你可以根据自己的实际情况调整参数值。希望这些经验能帮你少走弯路,快速定位Nginx反向代理的各种疑难杂症!