线上出现问题了你有思路解决吗
1. 线上服务器CPU使用率达到100%,如何排查、定位与解决呢
面试官通过这个问题来试探面试者,有没有真实的玩过线上的机器
导致CPU过高的一般原因
- 无线循环,例如递归调用等(可以整个sleep)
- 频繁GC(内存分配过快,导致区域很快就满了)
- 频繁创建新对象(可以考虑使用单例)
- 错误姿势的使用序列化和反序列化类库
- 正则表达式
- 线程上下文频繁切换
解决方法思路
- 使用Linux命令 top 到CPU占用最高的进程A pid1
- 再使用 top -Hp 拿到指定进程占用最高的线程 pid2
- 使用 printf %x pid2 将10进制线程号转换成16进制 8ccc
- 通过 jstack pid1 > dump.txt 获取进程A的堆栈快照
- 使用 cat dump.txt | grep -A 30 8ccc 根据16进制信息筛查出有问题的代码(往下展示30行)
- 排查代码中的问题并修复
2. 线上机器的一个进程使用kill命令无法杀死怎么办?
kill进程如果死活杀不死,那么这个进程会进入 zombie(僵尸) 状态,也就是一个僵尸进程,这是因为 子进程释放了资源,但是没有经过父进程的确认
解决方法思路
- 使用Linux命令 ps aux 查看 stat ,如果对应这一栏值是 Z ,那么说明是僵尸进程
- 使用 ps -ef | grep 僵尸进程id 可以找到 父进程id
- 使用 kill 杀死父进程即可
3. 磁盘空间快满了,不影响服务的情况下如何解决?
解决方法思路
- 使用Linux命令 df -h 查看磁盘使用率情况
- 可以通过删除一些年份比较久的日志文件来释放空间。(一般可以通过 crontab定时任务 来每天定时清理一些日志文件,保证空间富余)
- 如果不是日志文件导致,就通过 find \ -size +100M | xargs ls -lh (查询根目录下所有大于100M的文件)
- 如果没找到大文件,可以查询占据磁盘空间大的目录,看看各个目录里是否有大量的小文件, du -h > fs_du.log
4. 线上发生 java.lang.OutOfMemoryError Java heap space 堆内存溢出怎么办?
堆内存溢出的原因及解决思路
- 内存泄漏:找到堆栈引用链,查出哪个对象没有被回收导致内存泄漏(找到泄漏对象的创建位置)
- 非内存泄漏:考虑调大JVM参数的xms xmx最大\小堆内存,为应用分配更多的堆内存;检查代码,排除有些对象生命周期是否太长了,又或者存储结构不合理(有时换个方式存储对象可以节省很多内存)
现实可能发生堆内存溢出的场景
- 数据库过多数据返回给服务端,导致内存溢出:
- 根据某个分类搜索商品列表(分页),如果这个分类的商品特别多,并且pageSize没有设置限制,被恶意攻击时,会一下子就把内存打崩
- …
举个🌰说明
\**
* 使用该选项运行:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
使用最小\最大堆内存都为20m 并且在堆内存溢出时做一次堆dump
*\
public class HeapOOMTest {
private List<String> oomList = new ArrayList<>();
public static void main(String[] args) {
HeapOOMTest oomTest = new HeapOOMTest();
while (true) {
oomTest.oomList.add(UUID.randomUUID().toString());
}
}
}
按照配置运行代码,会发生堆内存溢出。
在实际项目中,堆内存溢出可能会导致进程崩溃,极端场景下进程可能直接就挂掉了,不会打印日志
项目根目录中,会生成dump文件,例如 java_pid15468.hprof
分析dump文件
- MAT
- VisualVM
- PerfMa
具体操作查看本人在有道云做的笔记
实战:堆内存溢出【java.lang.OutOfMemoryError Java heap space】
也可以查看以下文章
实战:OOM 后我如何分析解决的 | PerfMa应用性能技术社区
栈内存溢出:可能由 递归创建过多栈帧 导致栈内存溢出
方法区内存溢出:可能由 常量占据内存过多 导致元空间内存不足
5. 如果一个项目越跑越慢,你觉得可能是因为什么?
- 垃圾收集非常频繁,stop the world时间越来越长,导致项目执行越来越慢
- 数据库数据量变大(慢SQL优化或者分库分表来解决)
- Code Cache默认的240M代码缓存区满了。未满时,代码以编译的方式执行,如果满了,代码会以解释的方式执行,执行速度上比编译执行慢了一个数量级,严重影响项目性能
- 线程争抢过于激烈,导致代码争抢不到CPU时间片去执行任务
- 操作系统问题则重启大法好
代码缓存区相关知识点:实战:代码缓存区域满
可以通过 skywalking 来预防和辅助分析问题