现场突发问题排查与解决
问题描述
现象:服务重启后,5分钟就宕机,全部接口访问不通
排查过程
第一阶段:初步排查
问题发现
- 观察日志:发现查询数据库的地方一直不返回
- 日志问题:由于日志太多,不好观察,先增加日志
异常现象
- 查询数据库需要一个小时才返回
- 但是将 SQL 放到 Navicat 里面,立马返回
- 目前不太好定位是什么原因
第二阶段:解决方案尝试
方案1:本地缓存(失败 ❌)
思路:
- 服务启动后先将数据缓存到本地缓存中
- 查询走缓存,避免频繁查询数据库
为什么不用 Redis?
- 因为目前服务没有 Redis
- 引入 Redis 还需要加配置,太麻烦
- 目前需要尽快恢复服务使用
结果:
- 改造完成,上线以为万无一失
- 结果还是 5分钟宕机 ❌
方案2:去除锁和事务(失败 ❌)
分析:可能是因为服务中的锁导致
操作:
- 去除
synchronized - 去除事务注解
@Transactional - 去除读写锁
结果:
- 全都去掉后
- 结果还是宕机 ❌
第三阶段:深度排查
使用 jstack 分析线程堆栈
命令:
jstack pid > jstack.log
分析结果:

image.png
- 通过 jstack.log 发现问题
- 是 random 的问题!
根本原因
问题代码
private static Random random;
static {
try {
random = SecureRandom.getInstanceStrong();
} catch (NoSuchAlgorithmException e) {
LOGGER.error("Exception:NoSuchAlgorithmException!");
}
}
问题分析
SecureRandom.getInstanceStrong() 存在严重的阻塞问题:
-
阻塞式随机数生成
- 在 Linux 系统上使用
/dev/random - 这是一个阻塞式的随机数生成器
- 当系统熵池不足时,会阻塞等待
- 在 Linux 系统上使用
-
高并发场景下的问题
- 多个线程同时调用会导致严重的性能问题
- 线程挂起数秒甚至数分钟
- 最终导致服务宕机
最终解决方案 ✅
修改后的代码
private static Random random;
static {
try {
random = SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
random = new SecureRandom();
LOGGER.error("SHA1PRNG not available, using default SecureRandom");
}
}
方案说明
使用 SHA1PRNG 算法:
- 使用非阻塞式的随机数生成算法
- 避免依赖系统熵池
- 性能更好,不会阻塞线程
降级策略:
- 如果 SHA1PRNG 不可用,使用默认的 SecureRandom
- 记录错误日志,便于监控
结果
上线后,完美解决 ✅
- 服务稳定运行,不再宕机
- 所有接口正常访问
- 数据库查询正常返回
经验总结
排查思路
- ✅ 观察日志:关注异常和慢查询
- ✅ 对比测试:服务查询慢,但直接查询快 → 排除数据库问题
- ✅ 逐步排查:先排查缓存、锁、事务等常见问题
- ✅ 深度分析:使用 jstack 分析线程堆栈
关键工具
| 工具 | 用途 | 命令 |
|---|---|---|
| jstack | 分析线程堆栈 | jstack pid > jstack.log |
| 日志 | 观察异常和慢查询 | 增加关键位置的日志 |
| Navicat | 验证 SQL 性能 | 直接执行 SQL |
技术要点
SecureRandom 使用建议:
| 场景 | 推荐方案 | 说明 |
|---|---|---|
| 高并发生成随机数 | SecureRandom.getInstance("SHA1PRNG") |
非阻塞,性能好 |
| 普通随机数 | ThreadLocalRandom.current() |
最快,线程安全 |
| 加密场景 | new SecureRandom() |
安全性最高 |
| ❌ 不推荐 | SecureRandom.getInstanceStrong() |
会阻塞,容易宕机 |
注意事项
⚠️ 避免使用 SecureRandom.getInstanceStrong()
- 在生产环境中极易导致服务阻塞
- 特别是在高并发场景下
- Linux 系统上问题更严重
✅ 推荐做法
- 使用 SHA1PRNG 或 ThreadLocalRandom
- 增加日志记录,便于问题排查
- 定期使用 jstack 监控线程状态
解决状态:✅ 已完美解决