做后端开发的同学应该都知道,当服务出现不确定因素而导致的内存突然升高或者溢出是一件多么让人头疼的事情。尽管jdk本身给我们提供了一系列检查分析工具,但依然不够直观便捷的让你了解自己远程的服务运行的实时情况。本人在几次尝试后终于找到一款便捷,轻松掌控服务端进程的监控系统分享给大家,它就是今天的主角JavaMelody一款优秀的开源监控系统。可以从git上获取到相关项目https://github.com/javamelody/javamelody,至于配置相对简单再次不作为重点去说。首先看看他能监控到哪些内容:

图1

从图1可以看出JavaMelody给我们提供了进程的内存,cpu,访问量,http错误,sql使用等等一系列监控项。

图2

除了这些常规项外还提供了各接口响应次数和时长,这将会给后期的性能优化起到至关重要的帮助。当然除了这些还有sql的执行监控甚至到方法级的请求和执行监控等。这些监控指标可以帮助技术人员有效的了解到远端进程运行情况,有问题当然可以第一时间发现,比如我刚刚遇到的这个case:

图3

我们的系统新上线了版本,整体运行很良好,突然某天的5点左右一台服务器的内存呈现爆表式的增长,如上图所示,一柱擎天。看到这图后我们很惊讶,到底做了什么使平时稳定的内存爆涨?当时排查问题从以下几点入手:1、其他服务器突然停止服务导致所有请求到本机导致内存猛升?2、有什么定时任务导致突然加载了很多对象到内存里?3、垃圾回收出问题了?于是一个个去排查,首先其他服务器运行正常切无内存暴增的问题,所以第一点排除。第二步也排除了,因为当时没有定时任务启动执行,所以第二点也排除了。检查垃圾回收发现回收正常,ygc进行了600多次,而fullGC只有2次,回收没问题。但发现了一个奇怪的现象,old区百分比从20%突然增加到了47%,这27%的猛增就直接导致了内存的扩大。了解jvm垃圾回收的同学可以想到一个问题,那就是一定是有一个大的对象产生而躲开了YGC直接进入了old区,找到大对象的产生这个问题就迎刃而解。好吧,JavaMelody的作用要再次体现了。

图4

在JavaMelody里有一个内存直方图的东西,打开后可以看到内存中加载的类和对象。从下图可以看到一个自己应用的对象引起了我的注意:

图5

从图中可以看到这是一个第三方登录的方法,而这个方法竟然有40多万实体产生(上面这张图是从测试中取到的,实际线上比这多很多但没保存当时图片)。会不会和这有关?抓紧检查第三方登录的代码,一条语句引起了我们的注意,原来在获取第三方登录的openid的时候可能会是null,而这个没被检查判空,导致直接进入到sql,使得整张表的数据被检索出来扔进了list中。百万用户信息被扔进内存,不爆才怪嘞!问题定位到了,抓紧改bug,重新发布,看图舒服了。。。。。

图6

这次通过JavaMelody成功发现解决了这个问题,当然JavaMelody还有很多功能可以帮助我们定位解决问题,希望作者能持续更好的产出造福其他技术人员。通过这次bug又让我想起自己对团队的人说的一句话,技术人员要谨小慎微,要如履薄冰,一句代码不小心就可能搞挂一个系统。