Flink 提供的 Metrics 可以在 Flink 内部收集一些指标,通过这些指标让开发人员更好地理解作业或集群的状态。
第一,常用的如 Counter,写过 mapreduce 作业就应该很熟悉 Counter,就是对一个计数器进行累加,即对于多条数据和多兆数据一直往上加的过程。
第二,Gauge,Gauge 是最简单的 Metrics,它反映一个值。比如要看现在 Java heap 内存用了多少,就可以每次实时的暴露一个 Gauge,Gauge 当前的值就是 heap 使用的量。
第三,Meter,Meter 是指统计吞吐量和单位时间内发生“事件”的次数。它相当于求一种速率,即事件次数除以使用的时间。
第四,Histogram,Histogram 比较复杂,也不常用,Histogram 用于统计一些数据的分布,比如说 Quantile、Mean、StdDev、Max、Min 等。
Metric 在 Flink 内部有多层结构,以 Group 的方式组织,它并不是一个扁平化的结构,Metric Group + Metric Name 是 Metrics 的唯一标识。
Metric Group 的层级有 TaskManagerMetricGroup 和 TaskManagerJobMetricGroup,每个 Job 具体到某一个 task 的 group,task 又分为 TaskIOMetricGroup 和 OperatorMetricGroup。Operator 下面也有 IO 统计和一些 Metrics。
Metrics 不会影响系统,它处在不同的组中,并且 Flink支持自定义添加 Group。
JobManagerMetricGroup 相对简单,相当于 Master,它的层级也相对较少。
Metrics 定义还是比较简单的,即指标的信息可以自己收集,自己统计,在外部系统能够看到 Metrics 的信息,并能够对其进行聚合计算。
Metrics 主要是对 Flink 作业时的性能进行监控。包括
•CPU
•Memory
•Threads
•Garbage Collection
•Network
•Classloader
•Cluster
•Availability
•Checkpointing
•StateBackend
•IO
官方文档:https://ci.apache.org/projects/flink/flink-docs-release-1.10/monitoring/metrics.html
除了系统的 Metrics 之外,Flink 支持自定义 Metrics ,即 User-defined Metrics。对于自己的业务逻辑也可以用 Metrics 来暴露一些指标,以便进行监控。
User-defined Metrics 现在提及的都是 datastream 的 API,table、sql 可能需要 context 协助,但如果写 UDF,它们其实是大同小异的。
Datastream 的 API 是继承 RichFunction ,继承 RichFunction 才可以有 Metrics 的接口。然后通过 RichFunction 会带来一个 getRuntimeContext().getMetricGroup().addGroup(…) 的方法,这里就是 User-defined Metrics 的入口。通过这种方式,可以自定义 user-defined Metric Group。如果想定义具体的 Metrics,同样需要用getRuntimeContext().getMetricGroup().counter/gauge/meter/histogram(…) 方法,它会有相应的构造函数,可以定义到自己的 Metrics 类型中。
下面通过一段简单的例子说明如何使用 Metrics。比如,定义了一个 Counter 传一个 name,Counter 默认的类型是 single counter(Flink 内置的一个实现),可以对 Counter 进行 inc()操作,并在代码里面直接获取。
Meter 也是这样,Flink 有一个内置的实现是 Meterview,因为 Meter 是多长时间内发生事件的记录,所以它是要有一个多长时间的窗口。平常用 Meter 时直接 markEvent(),相当于加一个事件不停地打点,最后用 getrate() 的方法直接把这一段时间发生的事件除一下给算出来。
Gauge 就比较简单了,把当前的时间打出来,用 Lambda 表达式直接把 System::currentTimeMillis 打进去就可以,相当于每次调用的时候都会去真正调一下系统当天时间进行计算。
Histogram 稍微复杂一点,Flink 中代码提供了两种实现,在此取一其中个实现,仍然需要一个窗口大小,更新的时候可以给它一个值。
这些 Metrics 一般都不是线程安全的。如果想要用多线程,就需要加同步。
Counter processedCount = getRuntimeContext().getMetricGroup().counter("processed_count");
processedCount.inc();
Meter processRate = getRuntimeContext().getMetricGroup().meter("rate", new MeterView(60));
processRate.markEvent();
getRuntimeContext().getMetricGroup().gauge("current_timestamp", System::currentTimeMillis);
Histogram histogram = getRuntimeContext().getMetricGroup().histogram("histogram", new DescriptiveStatisticsHistogram(1000));
histogram.update(1024);
更多详情请参考链接:https://ci.apache.org/projects/flink/flink-docs-release-1.8/monitoring/metrics.html#metric-types
获取 Metrics 有三种方法:
获取 Metrics 的方式在物理架构上是怎样实现的?
WebUI 和 RESTful API 是通过中心化节点定期查询把各个组件中的 Metrics 拉上来的实现方式。其中,fetch 不一定是实时更新的,默认为 10 秒,所以有可能在 WebUI 和 RESTful API 中刷新的数据不是实时想要得到的数据;此外,fetch 有可能不同步,比如两个组件,一边在加另一边没有动,可能是由于某种原因超时没有拉过来,这样是无法更新相关值的,它是 try best 的操作,所以有时我们看到的指标有可能会延迟,或许等待后相关值就更新了。
红色的路径通过 MetricFetcher,会有一个中心化的节点把它们聚合在一起展示。而 MetricReporter 不一样,每一个单独的点直接汇报,它没有中心化节点帮助做聚合。如果想要聚合,需要在第三方系统中进行,比如常见的 TSDB 系统。当然,不是中心化结构也是它的好处,它可以免去中心化节点带来的问题,比如内存放不下等,MetricReporter 把原始数据直接 Reporter 出来,用原始数据做处理会有更强大的功能。
Flink 内置了很多 Reporter,对外部系统的技术选型可以参考,比如 JMX 是 java 自带的技术,不严格属于第三方。还有InfluxDB、Prometheus、Slf4j(直接打 log 里)等,调试时候很好用,可以直接看 logger,Flink 本身自带日志系统,会打到 Flink 框架包里面去。
Flink 内置了很多 Reporter,对外部系统的技术选型可以参考,详见:https://ci.apache.org/projects/flink/flink-docs-release-1.8/monitoring/metrics.html#reporter
Metric Rporter 怎么配置呢?
首先 Metrics Reporters 的名字用逗号分隔,然后通过 metrics.reporter.jmx.class 的 classname 反射找 reporter,还需要拿到 metrics.reporter.jmx.port 的配置,比如像第三方系统通过网络发送的比较多。但要知道往哪里发,ip 地址、port 信息是比较常见的。此外还有 metrics.reporter.your_monitor.class 是必须要有的,可以自己定义间隔时间,Flink 可以解析,不需要自行去读,并且还可以写自己的 config。
Metric Reporter 配置示例如下:
metrics.reporters: your_monitor,jmx
metrics.reporter.jmx.class: org.apache.flink.metrics.jmx.JMXReporter
metrics.reporter.jmx.port: 1025-10000
metrics.reporter.your_monitor.class: com.your_company.YourMonitorClass
metrics.reporter.your_monitor.interval: 10 SECONDS
metrics.reporter.your_monitor.config.a: your_a_value
metrics.reporter.your_monitor.config.b: your_b_value
首先,收集一些关键的 Metrics 作为决策依据,利用 Metric Reporter 收集 Metrics 到存储/分析系统 (例如 TSDB),或者直接通过 RESTful API 获取。
有了数据之后,可以定制监控规则,关注关键指标,Failover、Checkpoint,、业务 Delay 信息。定制规则用途最广的是可以用来报警,省去很多人工的工作,并且可以定制 failover 多少次时需要人为介入。
当出现问题时,有钉钉报警、邮件报警、短信报警、电话报警等通知工具。
自动化运维的优势是可以通过大盘Dashboard、报表的形式清晰的查看数据,通过大盘时刻了解作业总体信息,通过报表分析优化。
从发现问题开始,如果有 Metrics 系统,再配上监控报警,就可以很快定位问题。然后对问题进行剖析,大盘看问题会比较方便,通过具体的 System Metrics 分析,缩小范围,验证假设,找到瓶颈,进而分析原因,从业务逻辑、JVM、 操作系统、State、数据分布等多维度进行分析;如果还不能找到问题原因,就只能借助 profiling 工具了。
其原因在于这种问题是系统框架问题,任务慢的问题也需要经过多轮剖析才能得到明确的答案。
除了不熟悉 Flink 机制以外,大多数人的问题是对于整个系统跑起来是黑盒,根本不知道系统在如何运行,缺少信息,无法了解系统状态。此时,一个有效的策略是求助 Metrics 来了解系统内部的状况。
以上内容来自对 https://www.bilibili.com/video/av56364280/ 的学习总结。