【HDFS】--@Metric是如何生效的?
前言
在HDFS的jmx界面中,我们能够看到很多的监控指标,如下图:
在二次开发的过程中,我们需要自定义一些指标,然后暴露出来,那如何实现呢?这就需要我们了解HDFS的Metric体系。
0x00 实现自定义metric
实现自定义指标很简单,只需要使用@Metric注解即可。
然后可以在jmx界面中看到这个指标。
很简单对吧,接下来我们看看怎么实现的。
0x01 @Metric注解的实现
我们采用自顶向下来看:
首先从FSNamesystem类出发,在启动Namenode时,会调用startCommonServices方法,在startCommonServices方法中会注册jmx相关的Bean。
DefaultMetricsSystem.instance()返回一个MetricsSystemImpl对象。然后调用了register方法。
register的真正实现在MetricsSystemImpl#register方法中。
因为我是提前看了源码,所以这里直接告诉大家,在newSourceBuilder里会通过反射获取使用了@Metric注解的方法或者成员变量。然后放到Map里,用于最后的jmx输出。如下图所示:
我们选第二个foreach进行阅读,因为前面我们就是使用@Metric修饰方法来实现自定义metric的。点进此add方法之后,代码如下:
此add方法会用foreach确保方法有@Metric注解,然后再进行处理。
接下来有如下语句:factory.newForMethod(source, method, (Metric) annotation, registry);
点进newForMethod方法之前,观察一下newForMethod的参数:
source代表FSNamesysterm,method代表被@Metric修饰的方法,
annotation代表注解,registry则是存储metrics信息的的对象。
我们点进newForMethod方法去看一下:
这个方法的主要逻辑如下:
根据注解+方法构造出MetricsInfo对象,注解里的参数能够对应到MetricsInfo对象成员。
new出一个MethodMetric对象,代表从@Metric修饰的方法中获得的metric
将上一步new出的MethodMetric对象放入registry的Map中保存,key是注解里提供的name参数或者方法名(注解未传name参数的时候,默认是方法名)
返回这个方法代表的metric。
这个方法中调用的getInfo方法,就是用来从@Metric传入的参数中解析metric名的。比如上面我们写的例子是这样的:
@Metric({"MyMetrics", "test customer metrics"})
那么MyMetrics就用来当做指标的name,
test customer metrics就用来当做指标的description。
同时在new MethodMetric的时候,也会去计算指标值:
进到newImpl的case DEFAULT分支,调用了newTag方法。
newTag方法里面会调用method对象的invoke方法,得到用@Metric注解修饰的方法的返回值,作为metric的value,代码如下:
到此我们也就分析完@Metric的原理了。