> **标签**:#ASG #Tomcat #SpringBoot #MySQL #故障排查 #运维教训
写在前面
asg manager版本: V200R001C00SPC100
系统环境:centos7
工作中遇到一个之前没有遇到过的问题。根据指南安装好asg manager软件,正确绑定设备,本来使用一切正常。但是因为这个版本平台版本比较旧,本身配置上也有一些问题。平台运行一段时间后,会因为开发软件对内存的占用问题(不释放缓存),会一直吃内存,直到内存耗尽,导致软件卡顿。甚至时间长了会导致无法正常接受设备的日志。于是写了一个定时重启脚本。由于脚本权限问题周日未正常启动,手动启动程序,登录后出现页面疯狂跳转问题。
症状:软件在https://m-datacenter/,和https://m-datacenter/cas/login页面之间疯狂跳转。
-
用户名密码输入正确,**CAS 登录接口能正常返回**
-
用户体感:**"页面在闪烁"**
一、需要看的参数
1. 浏览器端(我用的谷歌)
|---------------------------------------|--------------------------------------|------------------------------------------|
| 工具 | 位置 | 用途 |
| ------ | ------ | ------ |
| 浏览器开发者工具 F12 → Network 面板 | 浏览器 | 看实时请求/响应、Status、Location、Cookie、PostData |
| HAR 文件导出 | 浏览器 → Network → 右键 → Save all as HAR | 完整请求快照,可离线分析 |
network面板勾选Preserve log(保留日志),通过采集日志后,发给AI分析。
HAR 聚合分析脚本(关键):
node -e "
const fs=require('fs');
const har=JSON.parse(fs.readFileSync('<HAR_FILE>','utf8'));
const m={};
har.log.entries.forEach(e=>{
const u=e.request.url.replace(/https?:\/\/\^\\/+/,'').split('?')0;
mu=mu||{n:0,s:{}};
mu.n++;
mu.se.response.status=(mu.se.response.status||0)+1;
});
Object.entries(m).sort((a,b)=>b1.n-a1.n).forEach((k,v)=>{
console.log(k.padEnd(60),'总数:',v.n,'状态:',JSON.stringify(v.s));
});
"
2. nginx 端
|-------------------|--------------------------------------------------------------------|-----------------------------------|
| 参数 | 位置 / 命令 | 看什么 |
| ------ | ---------- | -------- |
| 实际加载的配置 | `nginx -T 2>/dev/null` | location 块、upstream、listen |
| access 日志 | `/var/log/nginx/access.log` 或 `/var/log/nginx/host.access.log` | 请求状态、客户端 IP、转发到哪个 upstream |
| error 日志 | `/var/log/nginx/error.log` | upstream 连接失败、502、connect refused |
3. Tomcat 端
|--------------------|----------------------------------------------------------------------------------------------------|--------------------------------------------------------------------|
| 参数 | 位置 | 看什么 |
| ------ | ------ | -------- |
| 启动日志 | `/home/datacenter/tomcat-<MODULE>/logs/catalina.out` | `Server startup in XXX ms` / `Error deploying web application` |
| 应用日志 | `/home/datacenter/tomcat-<MODULE>/logs/<MODULE>-error.log` 或 `<MODULE>-info.log` | 业务异常、JDBC 异常 |
| 应用配置 | `/home/datacenter/tomcat-<MODULE>/webapps/<MODULE>/WEB-INF/classes/application*.properties` | JDBC URL、用户名、密码 |
| Servlet 映射 | `/home/datacenter/tomcat-<MODULE>/webapps/<MODULE>/WEB-INF/web.xml` | `<url-pattern>` vs 前端请求路径 |
4. 数据库端
|----------------------|------------------------------------------------------------|--------------------|
| 参数 | 位置 / 命令 | 看什么 |
| ------ | ---------- | -------- |
| 监听状态 | `ss -tlnp \ | grep 3306` |
| 进程启动时间 | `ps -o pid,lstart,cmd -p 13172` | 何时启动 |
| systemd 启停记录 | `journalctl -u mysqld --since "..." --until "..."` | 何时停止、何时启动 |
| 库存在性 | `mysql -udatacenter -p -h127.0.0.1 -e "show databases;"` | 目标库是否存在 |
| 用户权限 | `mysql -u<APP_DB_USER> -p -e "show databases;"` | 应用用的 mysql 用户是否能登录 |
| MySQL 错误日志 | `/var/log/mysqld.log` | 连接拒绝、权限错误 |
5. 服务器资源
|------------|------------------------------|-----------|
| 参数 | 命令 | 排除什么 |
| ------ | ------ | --------- |
| 内存 | `free -h` | OOM |
| 磁盘 | `df -h` | 磁盘满 |
| CPU | `top` | CPU 耗尽 |
| 文件描述符 | `cat /proc/sys/fs/file-nr` | fd 用尽 |
6. 防火墙/SELinux
|---------------|-------------------------------|------------|
| 参数 | 命令 | 排除什么 |
| ------ | ------ | --------- |
| iptables | `iptables -L -n` | 端口拦截 |
| ip6tables | `ip6tables -L -n` | IPv6 端口拦截 |
| SELinux | `getenforce` / `sestatus` | SELinux 拦截 |
二、排除错误症结
诊断这类"页面行为异常"问题,最有效的方法是逐层排除:先排除网络层、再排除应用层、最后排除服务层。
本案例的排除链:
|---------|--------------------|---------------------------------|-----------------------------------|
| # | 假设 | 验证方法 | 结果 |
| --- | ------ | --------- | ------ |
| 1 | 浏览器问题 | 换浏览器、清缓存 | ❌ 不需要(HAR 是服务端数据) |
| 2 | 前端 JS bug | 看 `index.js` 行为 | ❌ 不是根因(404 触发 catch,是症状不是原因) |
| 3 | nginx 转发路径错 | `nginx -T \ | grep location` |
| 4 | nginx upstream 连不上 | nginx error.log | ❌ 没 connect failed 报错 |
| 5 | DNS 解析问题 | `nslookup` | ❌ 全部走 IP |
| 6 | session 不通 | 看 Set-Cookie、看 AJAX 响应 | ❌ 3 个 manager 接口 89/91 正常 |
| 7 | 302 重定向循环 | HAR 聚合 status 分布 | ❌ 302 总共只 9 次 |
| 8 | 防火墙拦截 | `iptables -L` | ❌ Tomcat 自身连 MySQL 拒绝,防火墙不会拦截本机连接 |
| 9 | 资源耗尽 | `free -h`, `df -h` | ❌ 无报错 |
| 10 | MySQL 没启动 | `ss -tlnp \ | grep 3306` |
| 11 | MySQL 库缺失 | `show databases` | ❌ `ums` 库在 |
| 12 | MySQL 用户密码错 | `mysql -udatacenter -p` | ❌ 能登录 |
| 13 | MySQL 启动顺序错 | `ps -o lstart` 对比 Tomcat 启动时间 | ✅ **确证**(晚 13 分钟) |
关键排除法 :绕开 nginx 直连 Tomcat (curl http://localhost:<PORT>/...)。如果直连也是 404,nginx 没问题 ;如果直连正常但 nginx 转发 404,nginx 有问题。
三、确定症结
每排除一个假设后,剩下的"未排除"项就是候选根因。确证方法:
|---------------------------|-----------------------------------------|------------------------------------------------------------------------|
| 确证项 | 验证命令 | 本案例证据 |
| -------- | --------- | ---------- |
| Tomcat 在听端口 | `ss -tlnp \ | grep <PORT>` |
| Tomcat 应用没部署 | 直连 `/<MODULE>/` 看是否 404 | 404(说明 context 没注册) |
| Tomcat 应用启动失败 | `grep "Error deploying" catalina.out` | `Failed to execute CommandLineRunner` |
| 启动失败的根因 | 看 Caused by 链 | `JDBCConnectionException` → `ConnectException: Connection refused` |
| MySQL 启动晚于应用 | `ps -o lstart` + `journalctl` | MySQL 17:30:44,Tomcat 17:17:48(晚 13 分钟) |
| 重启 Tomcat 后恢复 | `tail catalina.out` | `Server startup in 15764 ms` |
确证的核心思路 :找到错误链的最底层 Caused by。本案例的链路:
Error deploying web application
→ LifecycleException: Failed to start component ...StandardContext\[/ums]
→ IllegalStateException: Failed to execute CommandLineRunner
→ CannotCreateTransactionException: Could not open JPA EntityManager
→ JDBCConnectionException: Unable to acquire JDBC Connection
→ CommunicationsException: Communications link failure
→ ConnectException: 拒绝连接 (Connection refused) ← 【根因】
沿着 Caused by 一层层剥洋葱,直到最底层,就是根因。
关键症结
通过浏览器开发者工具导出 HAR 文件分析:
|----------------------------------------------------------|------------|-----------|------------|
| 请求 | 总次数 | 200 | 404 |
| ------ | -------- | ----- | ----- |
| `POST /ums/loginQueryMenus.action` | **94** | **0** | **94** |
| `POST /manager/.../License_queryActivateSn.action` | 91 | 89 | 0 |
| `POST /datacenter/.../sysWarnMessage` | 91 | 89 | 0 |
| `GET /ums/logout` | 2 | 0 | 2 |
核心发现 :POST /ums/loginQueryMenus.action 100% 返回 404。
页面闪烁的循环机制:
登录 → WebUI 加载 → AJAX 取菜单 → 404 → jQuery catch 抛错
→ window.location.href = '/cas/login' → 又触发登录
根本原因
绕过 nginx 直接打 Tomcat 端口,也是 404。说明问题不在 nginx。
查看 UMS Tomcat 启动日志(grep -A 50 "Error deploying web application" /home/datacenter/tomcat-ums/logs/catalina.out):
Caused by: java.lang.IllegalStateException: Failed to execute CommandLineRunner
at com.abtnetworks.data.totems.userms.AppUserMS$Runner.run
at com.abtnetworks.data.totems.userms.license.LicenseManager.init
at com.abtnetworks.data.totems.userms.license.service.LicenseService.findAll
Caused by: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
Caused by: java.net.ConnectException: 拒绝连接 (Connection refused)
UMS 应用在 Spring Boot 启动阶段连不上 MySQL ,导致整个 ums.war 部署失败。Tomcat 8880 端口虽然在听,但没有任何 servlet 响应,所以所有请求返回 404。
启动时间线
MySQL 进程启动时间
ps -o pid,lstart,cmd -p 13172
Wed Aug 26 17:30:44 2026 /usr/sbin/mysqld
systemd journal 看停止时间
journalctl -u mysqld --since "2026-08-26 17:00" --until "2026-08-26 17:30"
17:12:06 Stopping MySQL Server...
17:12:08 Stopped MySQL Server.
|--------------|--------------------------------|
| 时间 | 事件 |
| ------ | ------ |
| 17:12:06 | MySQL 停止 |
| 17:17:48 | Tomcat 启动,开始部署 `ums.war` |
| 17:17:58 | UMS 启动 → 连 MySQL 失败 → 应用启动失败 |
| 17:30:44 | MySQL 启动(**晚于 UMS 13 分钟**) |
| 之后 | UMS 一直处于"启动失败"状态,直到手动重启 |
根本原因 :ASG Manager 的启动脚本(datacenter_startup.sh 或 systemd 服务)先停了 MySQL 再启动 Tomcat,但 MySQL 实际启动晚于 UMS 13 分钟。UMS 在那一刻连不上 MySQL,整个应用 context 部署失败。
处理方法
步骤 1:验证 MySQL 已就绪
MySQL 进程在跑
ps -o pid,lstart,cmd -p 13172
3306 端口在听
ss -tlnp | grep 3306
LISTEN 0 80 :::3306 :::* users:(("mysqld",pid=13172,fd=28))
MySQL 登录测试
mysql -udatacenter -p -h127.0.0.1 -P 3306 -e "show databases;"
Database
information_schema
manager
mysql
performance_schema
sys
totems
ums
xxl_job
步骤 2:直接 curl 验证 Tomcat 真的 404
绕过 nginx 直连 Tomcat
curl -i -X POST -H "Content-Type: application/x-www-form-urlencoded" \
-d "&token=blpurpkFJrp62z1FbG6mSYvD1M9B4Vmg" \
http://localhost:8880/ums/loginQueryMenus.action
HTTP/1.1 404
Content-Length: 0
如果返回 404,说明 Tomcat 在听端口但应用没部署。继续查 catalina.out。
步骤 3:确认是 MySQL 启动顺序问题
查启动错误堆栈
grep -A 50 "Error deploying web application" \
/home/datacenter/tomcat-ums/logs/catalina.out | head -80
关键错误信息:
- Failed to execute CommandLineRunner
- Unable to acquire JDBC Connection
- Connection refused
步骤 4:重启 UMS Tomcat(立即修复)
重启
sh /home/datacenter/tomcat-ums/bin/shutdown.sh
sleep 3
sh /home/datacenter/tomcat-ums/bin/startup.sh
sleep 15
验证启动成功(应该看到 Server startup in XXXX ms,不应该有 Error deploying)
tail -30 /home/datacenter/tomcat-ums/logs/catalina.out | grep -E "Server startup|Error deploying"
验证 AJAX 接口恢复
curl -i -X POST -H "Content-Type: application/x-www-form-urlencoded" \
-d "&token=blpurpkFJrp62z1FbG6mSYvD1M9B4Vmg" \
http://localhost:8880/ums/loginQueryMenus.action
应该返回 200
实测:UMS 重启后 15.6 秒启动成功,页面闪烁立即消失。
关键命令速查
HAR 文件 status code 聚合(Node.js)
node -e "
const fs=require('fs');
const har=JSON.parse(fs.readFileSync('<HAR_FILE>','utf8'));
const m={};
har.log.entries.forEach(e=>{
const u=e.request.url.replace(/https?:\/\/\^\\/+/,'').split('?')0;
mu=mu||{n:0,s:{}};
mu.n++;
mu.se.response.status=(mu.se.response.status||0)+1;
});
Object.entries(m).sort((a,b)=>b1.n-a1.n).forEach((k,v)=>{
console.log(k.padEnd(60),'总数:',v.n,'状态:',JSON.stringify(v.s));
});
"
关键日志过滤
journalctl -u mysqld --since "YYYY-MM-DD HH:MM" --until "YYYY-MM-DD HH:MM"
ps -o pid,lstart,cmd -p 13172
ss -tlnp | grep 3306
grep -A 50 "Error deploying web application" /home/datacenter/tomcat-ums/logs/catalina.out