arthas使用watch监控Java应用,监控过程中Java应用总是挂掉,不监控时不会挂,监控时cpu最大使用80%,内存也很足,请问,为何会导致应用挂掉?
根据异常可以明显看到说找不到tools.jar这个工具包了,还是回归到Kubernetes容器环境中因为精简了jre运行时环境导致jdk很多功能受限了。后面我做了一个非常规的事情,就是在完整的jdk中找到了这个tools.jar,丢到了jre里的lib目录中,继续尝试,但是还有问题,如下:
/opt/kl # java -jar arthas-boot.jar 1 [INFO] arthas-boot version: 3.1.0 [INFO] arthas home: /root/.arthas/lib/3.1.0/arthas [INFO] Try to attach process 1 [ERROR] Start arthas failed, exception stack trace: java.lang.UnsatisfiedLinkError: no attach in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867) at java.lang.Runtime.loadLibrary0(Runtime.java:870) at java.lang.System.loadLibrary(System.java:1122) at sun.tools.attach.LinuxVirtualMachine. (LinuxVirtualMachine.java:342) at sun.tools.attach.LinuxAttachProvider.attachVirtualMachine(LinuxAttachProvider.java:78) at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:250) at com.taobao.arthas.core.Arthas.attachAgent(Arthas.java:73) at com.taobao.arthas.core.Arthas. (Arthas.java:26) at com.taobao.arthas.core.Arthas.main(Arthas.java:100) [ERROR] attach fail, targetPid: 1 异常解析: 可以看到在补全了tools.jar之后,出现了新的异常信息java.lang.UnsatisfiedLinkError: no attach in java.library.path,表明可能我们缺的东西不是一点半点,我们知道attach功能是Arthas实现原理的两大原理之一。
attach:jdk1.6新增功能,通过attach机制,可以在jvm运行中,通过pid关联应用
instrument:jdk1.5新增功能,通过instrument俗称javaagent技术,可以修改jvm加载的字节码
然后Arthas和其他诊断工具一样,都是先通过attach链接上目标应用,通过instrument动态修改应用程序的字节码达到不重启应用而监控应用的目的
最后的救命稻草 使用完整的JDK中的java命令。
以上方式都试过不行之后,最后我把完整的JDK给下载到本地了,然后通过jdk的bin目录下的java命令启动arthas-boot.jar终于ok了,出现了熟悉的java进程选择界面:
/opt/kl/jdk1.8.0_191/bin # ./java -jar arthas-boot.jar [INFO] arthas-boot version: 3.1.0 [INFO] Found existing java process, please choose one and hit RETURN. * [1]: 1 org.apache.catalina.startup.Bootstrap 最后定位到的问题其实很简单,我记录了Arthas大盘中关于内存部分的图,如下:
上图从标题栏开始往下,分别是heap(堆内存)、eden_space(伊甸园区内存),survivor_space(幸存者区内存)、tenured_gen(老年代内存)。这张图是触发导出操作后的内存分布,堆内存从一开始的200M左右占用、到400M、到600M、一瞬间就飚升到900多兆了。最后从堆内存指标我们看到,总共989M,使用的内存已经飚升到988M了,这个时候其实应用已经挂了,Kubernetes容器已经在重启这个实例了。到这里基本已经到位到应用在容器中频繁挂掉重启问题的本质了。
但是为什么堆内存会这么小呢? 最终查明,有方面的原因:
1、因为我们这边都是spring boot应用,只有一个遗留的tomcat部署的应用,所以在镜像优化方面更偏向jdk基础基础镜像,而tomcat镜像没怎么关注,一开始对堆内存这块并没调优设置。
2、后面出现问题后,也确实想到过因为是导出报表导致应用挂掉,很可能是内存问题,设置过tomcat镜像内的堆内存大小,但是因为我们重新打包的镜像没有使用新的版本号,而是直接覆盖之前的版本,又使用Jenkins构建的,Jenkins所在主机拉过之前的镜像,导致镜像更新后,Jenkins打包时并没有去拉最新的调优过基础镜像。
解决问题 1、调优过的镜像加上新的版本号,让应用基于新的版本号构建镜像。或者清理下Jenkins所在主机的镜像,这个会导致第一次构建时速度变慢
2、优化导出报表的实现,我给的方案是,在导出大数据报表时,可以通过id分区,分别作业写入同一个服务器本地的文件中,然后让web容器映射下这个文件所在的目录,等所有分区的任务都结束后,直接组装一个文件下载链接返回给前端,让前端触发一次读文件操作即可。
最后尝试下jmap 除了使用Arthas外,最后还尝试了使用jmap工具,但是因为重新下载的JDK版本和主机jre版本不兼容,所有没用上。最后通过JDK发行的归档页面找到了对应的版本,还是成功的使用jmap -heap pid看到了内存情况,。内存分布也蛮清晰的,如:
/opt/kl/jdk1.8.0_191/bin # ./jmap -heap 1 Attaching to process ID 1, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.191-b12
using thread-local object allocation. Mark Sweep Compact GC
Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 3221225472 (3072.0MB) NewSize = 1073741824 (1024.0MB) MaxNewSize = 1073741824 (1024.0MB) OldSize = 2147483648 (2048.0MB) NewRatio = 2 SurvivorRatio = 8 MetaspaceSize = 21807104 (20.796875MB) CompressedClassSpaceSize = 1073741824 (1024.0MB) MaxMetaspaceSize = 17592186044415 MB G1HeapRegionSize = 0 (0.0MB)
Heap Usage: New Generation (Eden + 1 Survivor Space): capacity = 966393856 (921.625MB) used = 856023096 (816.3672409057617MB) free = 110370760 (105.25775909423828MB) 88.57911199302988% used Eden Space: capacity = 859045888 (819.25MB) used = 787314712 (750.8418197631836MB) free = 71731176 (68.4081802368164MB) 91.6499017104893% used From Space: capacity = 107347968 (102.375MB) used = 68708384 (65.52542114257812MB) free = 38639584 (36.849578857421875MB) 64.00529537736568% used To Space: capacity = 107347968 (102.375MB) used = 0 (0.0MB) free = 107347968 (102.375MB) 0.0% used tenured generation: capacity = 2147483648 (2048.0MB) used = 1521987528 (1451.4804153442383MB) free = 625496120 (596.5195846557617MB) 70.87306715548038% used
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。