使用Metrics方法级远程监控Java程序
本文以Spring Web的后台开发讲解。
上一篇讲解了如何使用jvisualvm
监控Java程序。虽然已经挺强大了,但是在实际的应用中依然不满足我们的需求。现在,我们想要监控应用程序中所有Controller
提供的接口的访问数量,频次,响应时长。Service
层方法的执行次数,执行时长,频次等等。以便之后对系统的性能优化做准备。这个时候jvisualvm
已经不能满足我们的需求了。
1 方法级监控Java程序的方案
这是我对于监控Java程序中的方案:
- 付费的,比如YourKit,JProfile等。我尝试了YourKit,功能确实强大,但是现在性能并不是我们现在的瓶颈,我们尽量使用不付费的。
- Metrics-Spring。Metrics-Spring需要在每个方法上使用注解。我们采用微服务架构,20多个服务,每个工程预计平均有100左右个方法要监控。如果是一开始就用这个我觉得还可以。
- Metrics+Spring AOP。从Metrics-Spring中可以看到,Metrics统计的信息基本满足我们的需求。我们的项目需求是统计
Controller
层和Service
层的方法。那么可以通过Spring中的切面完成我们的需求。
我调查的方案和分析基本这样,其他人如果有更好的方案可以提出一起探讨。
下面是讲解+部分代码,本次讲解还有后篇。在第二篇文后,
2 Metrics的功能
关于Metrics的使用方法,已经有很多文章介绍了,我在这里推荐我认为还不错的给大家,然后我再介绍的使用方法.
- Metrics介绍。这篇文章对Metrics的基本功能介绍的已经很全面了。
- Metrics-Spring官方文档。这篇文章介绍了Metrics与Spring的集成,但是文档感觉不全呀。
其他的文章我就不多分享了,感觉大同小异。没什么太大差别。
3 将Metrics相关类装载到Spring容器
要使用Metric,那么首先需要MetricRegistry
。我们需要提供Http的报表,所以我们需要将MetricsServlet
注册到Spring中,以便可以通过Http接口监控系统。下面代码我们将Http接口定义为:/monitor/metrics
。
|
|
4 提供可控的终端报表
另外,为了方便调试,我希望支持终端报表的方式,并且要可以配置打开和关闭,于是我使用另外一个配置类:
|
|
这样可以在工程中的application.properties
文件中,通过下面配置开启终端报表,而且自动开启,10秒钟一次报表:
|
|
5 为要监控的方法准备Timer
Metrics中可以统计的信息很多,其中Timer已经满足了我们需要的信息。
我为什么要先为监控的方法准备Timer,而不是在方法执行的时候再创建呢?原因有两点。
- 我们既关心方法被调,也关心它从来没有被调用,如果是在方法执行的时候再创建,那么我们就不知道是方法没有被监控还是方法没有被调用了。
- 我们之后打算直接对@RestController,@Controller和@Service注解进行切面。这种类级别的切面力度会包含我们不关心的方法,例如toString等方法,所以准备好关心的方法,调用的时候发现不是我们关心的方法直接放过。
我们使用MethodMonitorCenter
类来收集我们想要监控的方法。通过实现ApplicationContextAware
接口,在Spring容器装载完毕之后,会回掉setApplicationContext
方法,我们通过getBeansWithAnnotation
方法找到包含指定注解的类。然后对其进行过滤,并获取我们想要监控的方法。在最后我们通过metricRegistry.timer(method.toString());
方法为我们的关心的方法准备一个timer。
|
|
6 在切面中对方法进行监控
然后我们可以在切面中监控我们关心的方法。这里使用环绕式切面对RestController
,Controller
,和Service
三个注解做切面。这样就可以在方法之前和之后加一些监控代码。当进入around函数的时候,我们先去MetricRegistry中查找有没有对应的timer,如果没有说明是我们不关心的方法,那么我么就可以直接执行,如果存在,那么我就对其进行监控。详情可见代码:
|
|
7 效果
之后访问/monitor/metrics
接口,就可以以Json的数据格式获取监控结果。大家实验的时候记得把MethodMonitorCenter
类中的PACKAGE_NAME
常量换成自己的。
现在基本已经实现监控所有Controller,和Service层我们定义的方法了,但是代码依然有很大的优化空间。这些代码是我从Git的版本库中找出来的,自己没有再去尝试,如有问题欢迎留言。请谅解。目前我已经对代码进行了多处优化,优化内容将在下一篇讲解,并会附上源码。
最后欢迎关注我的个人公众号。聊天,唠嗑,都可以。