Java分析和定位问题需要注意九个点

第一,考虑“鸡”和“蛋”的问题。

比如,发现业务逻辑执行很慢且线程数增多的情况时,我们需要考虑两种可能性:

一是,程序逻辑有问题或外部依赖慢,使得业务逻辑执行慢,在访问量不变的情况下需要更多的线程数来应对。比如,10TPS 的并发原先一次请求 1s 可以执行完成,10 个线程可以支撑;现在执行完成需要 10s,那就需要 100 个线程。

二是,有可能是请求量增大了,使得线程数增多,应用本身的 CPU 资源不足,再加上上下文切换问题导致处理变慢了。

第二,考虑通过分类寻找规律。

在定位问题没有头绪的时候,我们可以尝试总结规律。

比如,我们有 10 台应用服务器做负载均衡,出问题时可以通过日志分析是否是均匀分布的,还是问题都出现在 1 台机器。又比如,应用日志一般会记录线程名称,出问题时我们可以分析日志是否集中在某一类线程上。再比如,如果发现应用开启了大量 TCP 连接,通过 netstat 我们可以分析出主要集中连接到哪个服务。如果能总结出规律,很可能就找到了突破点。

第三,分析问题需要根据调用拓扑来,不能想当然。

比如,我们看到 Nginx 返回 502 错误,一般可以认为是下游服务的问题导致网关无法完成请求转发。对于下游服务,不能想当然就认为是我们的 Java 程序,比如在拓扑上可能 Nginx 代理的是 Kubernetes 的 Traefik Ingress,链路是 Nginx->Traefik-> 应用,如果一味排查 Java 程序的健康情况,那么始终不会找到根因。
又比如,我们虽然使用了 Spring Cloud Feign 来进行服务调用,出现连接超时也不一定就是服务端的问题,有可能是客户端通过 URL 来调用服务端,并不是通过 Eureka 的服务发现实现的客户端负载均衡。换句话说,客户端连接的是 Nginx 代理而不是直接连接应用,客户端连接服务出现的超时,其实是 Nginx 代理宕机所致。

第四,考虑资源限制类问题。

观察各种曲线指标,如果发现曲线慢慢上升然后稳定在一个水平线上,那么一般就是资源达到了限制或瓶颈。

比如,在观察网络带宽曲线的时候,如果发现带宽上升到 120MB 左右不动了,那么很可能就是打满了 1GB 的网卡或传输带宽。又比如,观察到数据库活跃连接数上升到 10 个就不动了,那么很可能是连接池打满了。观察监控一旦看到任何这样的曲线,都要引起重视。

第五,考虑资源相互影响。

CPU、内存、IO 和网络,这四类资源就像人的五脏六腑,是相辅相成的,一个资源出现了明显的瓶颈,很可能会引起其他资源的连锁反应。

比如,内存泄露后对象无法回收会造成大量 Full GC,此时 CPU 会大量消耗在 GC 上从而引起 CPU 使用增加。又比如,我们经常会把数据缓存在内存队列中进行异步 IO 处理,网络或磁盘出现问题时,就很可能会引起内存的暴涨。因此,出问题的时候,我们要考虑到这一点,以避免误判。

第六,排查网络问题要考虑三个方面

到底是客户端问题,还是服务端问题,还是传输问题。

比如,出现数据库访问慢的现象,可能是客户端的原因,连接池不够导致连接获取慢、GC 停顿、CPU 占满等;也可能是传输环节的问题,包括光纤、防火墙、路由表设置等问题;也可能是真正的服务端问题,需要逐一排查来进行区分。
服务端慢一般可以看到 MySQL 出慢日志,传输慢一般可以通过 ping 来简单定位,排除了这两个可能,并且仅仅是部分客户端出现访问慢的情况,就需要怀疑是客户端本身的问题。对于第三方系统、服务或存储访问出现慢的情况,不能完全假设是服务端的问题。

第七,快照类工具和趋势类工具需要结合使用。

比如,jstat、top、各种监控曲线是趋势类工具,可以让我们观察各个指标的变化情况,定位大概的问题点;而 jstack 和分析堆快照的 MAT 是快照类工具,用于详细分析某一时刻应用程序某一个点的细节。
一般情况下,我们会先使用趋势类工具来总结规律,再使用快照类工具来分析问题。如果反过来可能就会误判,因为快照类工具反映的只是一个瞬间程序的情况,不能仅仅通过分析单一快照得出结论,如果缺少趋势类工具的帮助,那至少也要提取多个快照来对比。

第八,不要轻易怀疑监控。

比如一个空难事故的分析,飞行员在空中发现仪表显示飞机所有油箱都处于缺油的状态,他第一时间的怀疑是油表出现故障了,始终不愿意相信是真的缺油,结果飞行不久后引擎就断油熄火了。 同样地,在应用出现问题时,我们会查看各种监控系统,但有些时候我们宁愿相信自己的经验,也不相信监控图表的显示。这可能会导致我们完全朝着错误的方向来排查问题。 如果真的怀疑是监控系统有问题,可以看一下这套监控系统对于不出问题的应用显示是否正常,如果正常那就应该相信监控而不是自己的经验。

 

第九,如果因为监控缺失等原因无法定位到根因的话,相同问题就有再出现的风险

需要做好三项工作:

1. 做好日志、监控和快照补漏工作,下次遇到问题时可以定位根因;
2. 针对问题的症状做好实时报警,确保出现问题后可以第一时间发现;
3. 考虑做一套热备的方案,出现问题后可以第一时间切换到热备系统快速解决问题,同时又可以保留老系统的现场。

 

原文链接:https://time.geekbang.org/column/article/221982

 

posted @ 2022-08-08 16:56  白玉神驹  阅读(146)  评论(0编辑  收藏  举报