文章

halo502故障排查

问题现象:

网站好久没管过了,今天访问站点时突然发现页面返回:

502 Bad Gateway
openresty

之前偶尔也有过,重启服务器后就好了,但这次是长时间的502,各个容器和服务器重启都没用。正好有闲时间,顺便看看到底怎么个事😏

先分析一下,OpenResty 本身收到了请求,但它反向代理的后端服务没有正常响应。因此初步判断问题不一定在 OpenResty,而更可能在后端服务、反代地址、Docker 网络或应用进程上。由于网站的配置啥的都忘了,所以得一步步查了

检查OpenResty配置是否正常:

首先检查nginx配置是否正确:

docker ps -a

都正常,说明主配置没有问题

查看主配置文件“/usr/local/openresty/nginx/conf/nginx.conf”

cat /usr/local/openresty/nginx/conf/nginx.conf

发现真正的站点配置并不在主配置文件里,继续查看 conf.d 目录下的站点配置文件

cd /usr/local/openresty/nginx/conf/conf.d/

cat missmoon.cn.conf

server {
    listen 80 ; 
    server_name missmoon.cn; 
    index index.php index.html index.htm default.php default.htm default.html; 
    proxy_set_header Host $host; 
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
    proxy_set_header X-Forwarded-Host $server_name; 
    proxy_set_header X-Real-IP $remote_addr; 
    proxy_http_version 1.1; 
    proxy_set_header Upgrade $http_upgrade; 
    proxy_set_header Connection $http_connection; 
    access_log /www/sites/missmoon.cn/log/access.log main; 
    error_log /www/sites/missmoon.cn/log/error.log; 
    location ^~ /.well-known/acme-challenge {
        allow all; 
        root /usr/share/nginx/html; 
    }
    location / {
        proxy_pass http://127.0.0.1:8090; 
    }
}

OpenResty把请求交给后端8090端口上处理,error_log /www/sites/missmoon.cn/log/error.log,访问看看

2026/04/21 23:52:01 [error] 167#167: *101 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 117.148.66.119, server: missmoon.cn, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8090/", host: "missmoon.cn"

OpenResty连接到了后端,但后端主动重置了连接,后端在返回完整响应头之前就提前关闭了连接,而且OpenResty 甚至无法连接到127.0.0.1:8090

所以可以确定:502的直接原因是OpenResty的上游服务异常

检查halo容器

博客使用的是halo,采用docker部署

f

halo容器显示:health: starting,继续查看halo容器日志

docker logs --tail 200 1Panel-halo-FqEf

输出关键语句:
Failed to obtain R2DBC Connection
Plugin 'mysql_native_password' is not loaded

说明 Halo 启动失败的真正原因是:Halo在连接 MySQL 数据库时认证失败,无法获得数据库连接

搜了搜这个“mysql_native_password”,是MySQL的一种密码认证插件,控制用户密码怎么加密、怎么校验登录等,客户端(比如 Halo)登录 MySQL 时,数据库用什么规则来验证密码。之前升级过mysqlde版本,从8.0.45升级到8.4.9,8.4.9版本已经不用改插件了,采用caching_sha2_password

假设用户名为root,密码为root

正常流程:
1. Halo 发起连接
2. MySQL 说:这个用户用 mysql_native_password
3. 双方按 mysql_native_password 的规则进行“密码验证”
4. 验证成功 → 登录成功

现在是:
MySQL:这个插件不存在/没加载
→ 无法验证密码
→ 登录失败

Halo使用的是Spring Boot,默认行为是:如果关键 Bean(组件)初始化失败 → 应用直接启动失败,数据库连接正属于“DataSource / ConnectionFactory(核心 Bean)”,所以完整的链路可能是

mysql认证失败->halo无法连接数据库->Spring Boot在初始化阶段直接终止应用启动,最终表现为容器未正常运行,即halo容器启动失败->8090没有正常服务->OpenResty 反代失败->502 Bad Gateway

解决:

运维面板用的是1panel,发现mysql和halo都有备份,但是mysql的备份还是两年前的,halo的备份是截至到上次文章更新。按照chatgpt的方法修改当前数据库的配置,依旧502,而且无法保证物理数据目录向下兼容。查看了下halo的备份,存在一个halo.sql文件。该sql文件包含一个extension的表,Halo 2.x 采用资源注册式数据结构,文章、用户、附件等所有业务数据均以 JSON 形式存储在该表中,因此该备份实际包含完整的博客内容数据。所以直接导入该备份,访问域名一切正常。

数据库的原因后面有时间再解决吧

解决Plugin ‘mysql_native_password‘ is not loaded_mysql native password-CSDN博客

MySQL8.0升级到MySQL8.4避坑:密码插件问题-腾讯云开发者社区-腾讯云

总结:

本次502主要是由于MySQL 8.4 版本中认证插件变更, Halo 无法完成数据库认证并启动失败导致的,同时在处理过程中因不规范修改用户表进一步造成用户体系损坏。

以后必须得定期进行相关数据的备份,尽量不做版本过大的升级,对相关配置进行修改的时候也得做好备份

License:  CC BY 4.0