2.2 访问报错:502 / 504 / 404 与反向代理排错

先给一个判断

502 是“后端没接电话”,504 是“后端接了电话没说话”,404 是“前台找不到这个分机号”。 三个码对应请求路径上三个不同的故障点,弄清这一点,排错方向就不会错。OpenResty 是前台,后端是你的应用或运行环境;前台能正常响应,说明 OpenResty 本身没事,去查它背后的东西。

现象速查表:先对号入座

状态码 含义 最可能的原因 排查起点
502 网关错误 后端服务挂了 / 没监听对端口 后端容器或进程状态
504 网关超时 后端太慢,代理等不及 后端性能、超时配置
404 找不到 路径不对 / 代理地址错 / 默认文档缺失 网站目录与代理配置
502 间歇出现 时好时坏 后端负载高或频繁重启 后端日志、监控
全站 502(所有网站) 一起挂 OpenResty 自身异常 OpenResty 状态与日志

记住 02-0 里的规律:全挂先看 OpenResty,单个挂先看那个网站的配置和日志。

定位:从错误日志开始

入口:日志审计 → 网站日志,选一个网站,看 OpenResty 的错误日志。错误日志会明确写出类似“connection refused while connecting to upstream”或“upstream timed out”这样的原文,直接指向问题。

在服务器上也可以直接看:

# 找到 OpenResty 容器(具体名称以应用商店安装的为准)
docker ps --filter "name=openresty"

# 看最近的错误日志(容器名按实际替换)
docker logs --tail 100 1panel-openresty 2>&1 | grep -i "error\|upstream"

一个真实的工作习惯:开两个浏览器标签,一个看错误日志,一个改配置。改一次,切过去看日志有没有新报错,比“改了试、试了再猜”快十倍。

修复:502 —— 后端没接电话

第一步:确认后端在不在。

# 运行环境类网站:查后端进程/容器
docker ps | grep -E "php|node|java|python"

# 一键部署类网站:查应用容器
docker ps | grep -i wordpress

容器是 Exited 或 Restarting 状态,先看它的日志找死因:

docker logs --tail 200 容器名

第二步:确认端口对不对。 后端进程活着,但 OpenResty 找的是另一个端口,照样 502。在网站配置的“反向代理”或创建时的代理地址里核对。

# 本地直连后端端口验证(绕过 OpenResty)
curl -I http://127.0.0.1:后端端口/

本地能通,说明是 OpenResty 到后端的配置问题;本地不通,后端自己有问题。

第三步:容器网络。 后端跑在容器里、OpenResty 也跑在容器里,两者不在同一个 Docker 网络时,127.0.0.1 可能互相够不着。用容器名/服务名访问,或者检查网络设置(容器网络排错见 3.3 节)。

修复:504 —— 后端太慢

504 是后端有能力响应,但超过代理的超时时间。两个方向:

方向 动作
治标 在网站配置的反向代理中调大超时时间
治本 查后端为什么慢:数据库慢查询、PHP 进程数不够、内存不足

后端慢的根因往往不在网站这边。PHP 网站可以先查运行环境的进程守护配置和 PHP 配置;数据库慢查询看数据库设置里的慢日志(见 4.3 节)。

边界提醒:调超时只是给后端更多时间,如果后端本来就慢到 60 秒,调到 120 秒只是让用户多等一分钟。先定位慢在哪。

修复:404 —— 分两种情况

情况 A:静态网站 / 运行环境网站报 404。 先确认文件真的在那儿:

# 进网站目录看文件在不在(路径换成你的网站目录)
ls -la /opt/1panel/www/sites/你的网站/index/

再看默认文档配置(网站配置 → 默认文档),里面的文件名要和实际入口文件一致,顺序也有讲究——index.html 在前就不会去加载 index.php。

情况 B:反向代理网站报 404。 问题几乎都在代理路径上。核对两点:

  1. 代理地址对不对(含端口、含路径前缀);
  2. 后端服务的路由是否认识传过去的路径。

典型例子:前端代理到 http://127.0.0.1:3000,但前端应用部署在 /app 路径下,访问 你的域名/app 才行,访问根路径自然 404。

情况 C:负载均衡的坑。 网站配置里可以建负载均衡规则,把请求转到多个后端。创建反向代理时代理地址要写成 http://<负载均衡名称> 才会真正生效。如果Load balance 建了但代理地址还是指向单台后端,请求根本不会分流,某台后端挂了就直接 502,而你还以为有高可用。去网站配置的负载均衡和反向代理两个页面对一遍。

反向代理的两个经典坑

坑一:WebSocket 不通

官方 FAQ 明确记载:用自建 Nginx 反向代理 1Panel(或任何依赖 WebSocket 的服务),必须加上这三行,否则面板终端、容器终端这类功能全部用不了:

location / {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

官方还给了个偷懒办法:直接在 1Panel 里新建一个反向代理网站,这些都自动带上。

坑二:跨域(CORS)报错

前后端分离部署时,浏览器控制台报 CORS policy 开头的错误,是跨域拦截。在网站配置的 CORS 页面配置允许来源、方法、请求头。

一个硬规则:允许携带凭证(Cookie)时,允许来源不能配成通配的 *,必须写具体的域名。这是浏览器的规范,不是 1Panel 的限制。详见 2.4 节。

一个完整的复现与修复

现象:WordPress 网站突然全站 502,首页都打不开。

排查过程:

  1. 先确认是不是全挂——同服务器另一个静态网站访问正常。排除 OpenResty,锁定这个网站的后端。
  2. 看网站日志的错误日志,反复出现“connection refused”,后端连不上。
  3. docker ps 发现 PHP 运行环境容器是 Exited 状态,docker logs 显示内存不足被杀。

修复:服务器内存本来就紧张,先重启运行环境恢复网站,然后把 PHP 的进程数调小一点,并整治占内存的数据库(过程见 4.3 节),之后没再复发。

复盘要点:502 的第一动作永远是“看是不是全挂”,这一个动作就能决定后面查 OpenResty 还是查后端。

验证

# 1. 确认状态码(-I 只看头)
curl -I http://你的域名/

# 2. 模拟 Host 头访问(域名没解析时也能测)
curl -I -H "Host: 你的域名" http://服务器IP/

# 3. 本地直连后端
curl -I http://127.0.0.1:后端端口/

第 2 条特别有用:域名解析还没生效或者用 CDN 时,用 Host 头能直接测到 OpenResty 的真实响应,bypass 掉 DNS 和 CDN 的干扰。

还有一个容易被忽略的验证点:改完网站配置要点保存,然后观察是否需要重载 OpenResty。OpenResty 的“重载”按钮在网站列表上方工具栏,不停机应用新配置;如果配置改了但没生效,先确认这一步做了没有。

本节要点

  • 502 查后端死活,504 查后端速度,404 查路径和代理地址;
  • 全站挂看 OpenResty,单个挂看那个网站的配置和日志;
  • 反代 WebSocket 必须加 Upgrade / Connection 头,官方 FAQ 有原文;
  • CORS 带凭证时来源不能配 *;
  • 排错时善用 curl -H "Host: ..." 绕过 DNS。

网站配置的各项入口(域名、目录、默认代理、CORS、伪静态等)都在网站列表的【配置】里,详见 1Panel 官方文档:网站配置。

下一节:网站能打开了,但 HTTPS 证书申请不下来、快到期了也没续上——域名解析和证书的坑,一个比一个隐蔽。