Flink源码系列——指标监测

本文详细介绍了Flink的Metric系统,包括Metric、MetricGroup、MetricReporter和MetricRegistry。Metric作为基本度量单位,包含Gauge、Counter、Meter和Histogram。MetricGroup用于组织和管理Metric,形成树状结构。MetricReporter则负责对外发布Metric信息。重点讨论了MetricRegistry在两者之间的协调作用,以及Metric添加、更新和查询的流程。
摘要由CSDN通过智能技术生成

1、Metric简介

Flink对于指标监测有一套自己的实现,指标的统计方式有四种,这些指标都实现了Metric这个接口,而Metric这个接口只是一个标识,本身并没有定义如何方法接口,部分子类的继承关系如下所示。
这里写图片描述
从图中可以看出,Metric这个接口有四个直接子类,分别是:

Gauge —— 最简单的度量指标,只是简单的返回一个值,比如返回一个队列中当前元素的个数;
Counter —— 计数器,在一些情况下,会比Gauge高效,比如通过一个AtomicLong变量来统计一个队列的长度;
Meter —— 吞吐量的度量,也就是一系列事件发生的速率,例如TPS;
Histogram —— 度量值的统计结果,如最大值、最小值、平均值,以及分布情况等。

以MeterView为例,分析一个Metric的具体实现。MeterView还实现View接口,实现View接口的类,表示其会定期的执行update方法,进行数据的更新。

public class MeterView implements Meter, View {
   
   /** 底层使用的计算器 */
   private final Counter counter;
   /** 计算平均值的事件跨度 */
   private final int timeSpanInSeconds;
   /** 包含历史数据的循环数组 */
   private final long[] values;
   /** 当前时间在数组中的索引 */
   private int time = 0;
   /** 最新计算的rate */
   private double currentRate = 0;

   public MeterView(int timeSpanInSeconds) {
      this(new SimpleCounter(), timeSpanInSeconds);
   }

   public MeterView(Counter counter, int timeSpanInSeconds) {
      this.counter = counter;
      /** 这里的操作是为了让时间跨度刚好是 UPDATE_INTERVAL_SECONDS 的整数倍 */
      this.timeSpanInSeconds = timeSpanInSeconds - (timeSpanInSeconds % UPDATE_INTERVAL_SECONDS);
      this.values = new long[this.timeSpanInSeconds / UPDATE_INTERVAL_SECONDS + 1];
   }

   @Override
   public void markEvent() {
      this.counter.inc();
   }

   @Override
   public void markEvent(long n) {
      this.counter.inc(n);
   }

   @Override
   public long getCount() {
      return counter.getCount();
   }

   @Override
   public double getRate() {
      return currentRate;
   }

   @Override
   public void update() {
      time = (time + 1) % values.length;
      values[time] = counter.getCount();
      currentRate =  ((double) (values[time] - values[(time + 1) % values.length]) / timeSpanInSeconds);
   }
}

从类的属性变量中可以看出,MeterView是在一个Counter计数器的基础之上,封装了一层,从而实现事件每秒的平均速率。以values这个长整型的数组,作为环形数组,实现对最新的历史数据的保存。
在构造函数中,会对入参timeSpanInSeconds这个时间跨度进行修正,使其刚好是UPDATE_INTERVAL_SECONDS的整数倍,另外values数组的长度是timeSpanInSeconds对UPDATE_INTERVAL_SECONDS倍数,再加上1,这样这个数组的最新数据和最老的数据之间的时间间隔就刚好是timeSpanInSeconds。
假设values数组的长度为n,则:

1、索引n-1处的统计值,和索引0处的统计值,时间间隔就是timeSpanInSeconds;
2、由于是环形数组,所以索引0处的统计值,和索引1处的统计值的时间间隔就是timeSpanInSeconds;
3、所以索引i处的统计值,和索引(i+1)%n处的统计值,时间间隔是timeSpanInSeconds;

这个逻辑理清楚了,对update方法的逻辑也就清楚了。

另外,对于Metrics相关概念,可以参考 http://wuchong.me/blog/2015/08/01/getting-started-with-metrics/


2、MetricGroup

为了便于对Metric进行方便的管理和区分,可以对Metric进行分组,MetricGroup就是用来实现这个功能的。
MetricGroup的相关子类的继承关系如下所示。
这里写图片描述

1、ProxyMetricGroup —— 这是一个代理类,就是把新Metric或者新的子MetricGroup的注册,委托给代理MetricGroup进行处理;
2、AbstractMetricGroup —— 对新增Metric和子MetricGroup的相关方法进行了实现;

在AbstractMetricGroup中有这些属性

protected final A parent;
private final Map<String, Metric> metrics = new HashMap<>();
private final Map<String, AbstractMetricGroup> groups = new HashMap<>();

parent —— 用来保存这个MetricGroup的父MetricGroup
metrics —— 这个map,是用来保存当前MetricGroup中注册的Metric;
groups —— 这个map,是用来保存当前MetricGroup中注册子MetricGroup;

通过这个数据结构可以看出,在MetricGroup中,可以建立一个树状的结构,用来存储和归类相关的Metric。


3、MetricReporter

MetricReporter是用来向外披露Metric的监测结果的接口。
由于MetricReporter的子类在实例化时,都是通过反射机制,所以对于其实现子类,需要有一个公共,无参的构造函数,这个接口的定义如下:

public interface MetricReporter {
   void open(MetricConfig config);
   void close();
   void notifyOfAddedMetric(Metric metric, String metricName, MetricGroup group);
   void notifyOfRemovedMetric(Metric metric, String metricName, MetricGroup group);
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值