4. 指标采集:JMX、Prometheus Pushgateway、自定义Metric Reporter、Flink内置指标
监控系统能不能干活,关键看指标能不能采上来。说白了,你连数据都拿不到,后面那些告警、大盘、根因分析全是空谈。
这一章我们聊聊Flink指标采集的四种主流方式。每种方式都有它的适用场景,也有各自的坑。我这些年踩过的雷,今天一并说清楚。
4.1 Flink内置指标——开箱即用的基础数据
Flink本身自带了一套指标系统,你不需要额外写代码就能拿到。这些指标覆盖了Job、Task、算子、网络、内存、IO等方方面面。
我个人习惯把内置指标分成三类:
| 分类 | 典型指标 | 说明 |
|---|---|---|
| Job级别 | numRestarts、lastCheckpointSize、numberOfFailedCheckpoints | 反映作业整体健康度 |
| Task级别 | numRecordsInPerSecond、numRecordsOutPerSecond、currentInputWatermark | 反映算子处理能力与延迟 |
| 网络与内存 | inPoolUsage、outPoolUsage、memorySegmentsAvailable | 反映资源瓶颈 |
举个例子,配置Prometheus Reporter:
metrics.reporter.prom.class: org.apache.flink.metrics.prometheus.PrometheusReporter
metrics.reporter.prom.port: 9250
启动后访问 http://<taskmanager>:9250 就能看到Prometheus格式的指标。
4.2 JMX——Java生态的老牌选手
JMX(Java Management Extensions)是Java自带的监控管理框架。Flink的指标系统默认就注册到了MBean Server上,你可以用JConsole、VisualVM或者JMX客户端直接连上去看。
嗯,这里要注意。JMX虽然方便,但在生产环境里我一般不推荐直接用它做指标采集。为什么?
- 性能开销:频繁的JMX轮询会触发Full GC,尤其是当MBean数量多的时候。
- 安全性:JMX默认不加密,暴露在外网就是找死。
- 扩展性:JMX是点对点的,不适合大规模集群。
我曾经在一个大集群上直接用JMX拉指标,结果把TaskManager的GC时间拉高了30%。从那以后,JMX我只用来做临时调试,生产环境还是走Prometheus。
4.3 Prometheus Pushgateway——适合短生命周期任务
Prometheus默认是拉模式(Pull),但Flink作业是动态的,TaskManager随时可能扩缩容。拉模式需要服务发现,配置起来比较麻烦。
Pushgateway的出现解决了这个问题。Flink把指标推给Pushgateway,Prometheus再从Pushgateway拉。这样一来,你就不需要维护服务发现了。
配置方式也很简单:
metrics.reporter.promgateway.class: org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporter
metrics.reporter.promgateway.host: pushgateway.example.com
metrics.reporter.promgateway.port: 9091
metrics.reporter.promgateway.jobName: my_flink_job
metrics.reporter.promgateway.randomJobNameSuffix: true
这里有个坑——Pushgateway不会自动清理过期指标。如果你的作业重启了,旧的指标还留在Pushgateway里,会导致数据混乱。
我的做法是:在作业启动时,先调用Pushgateway的API删除旧指标,再开始推送。
curl -X DELETE http://pushgateway:9091/metrics/job/my_flink_job
4.4 自定义Metric Reporter——按需定制
内置的Reporter不一定满足所有场景。比如你想把指标写入Elasticsearch、InfluxDB或者自研的监控系统,那就得自己写Reporter。
实现一个自定义Reporter其实不复杂,核心就三步:
- 实现
org.apache.flink.metrics.reporter.MetricReporter接口 - 在
open()方法里初始化连接 - 在
report()方法里把指标发出去
我贴一个简化版的HTTP Reporter示例:
public class HttpReporter implements MetricReporter {
private HttpClient client;
private String endpoint;
@Override
public void open(MetricConfig config) {
this.endpoint = config.getString("endpoint", "http://localhost:8080/metrics");
this.client = HttpClient.newHttpClient();
}
@Override
public void report() {
// 遍历所有注册的指标,组装成JSON发送
String json = buildJsonFromMetrics();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(endpoint))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
client.sendAsync(request, HttpResponse.BodyHandlers.discarding());
}
@Override
public void close() {
client.close();
}
}
4.5 四种方式对比与选型建议
说了这么多,到底该用哪种?我整理了一张对比表:
| 方式 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
| Flink内置指标 | 零配置、覆盖全面 | 需要配合Reporter才能外发 | 所有场景的基础监控 |
| JMX | 原生支持、调试方便 | 性能差、不安全、不适合大规模 | 开发调试、临时排查 |
| Prometheus Pushgateway | 无需服务发现、配置简单 | 指标残留、单点故障 | 短生命周期任务、批处理 |
| 自定义Metric Reporter | 完全可控、灵活 | 开发成本高、需要维护 | 对接自研监控系统 |
我个人推荐的生产方案是:内置指标 + Prometheus Pull模式。配合Kubernetes的服务发现,基本能覆盖99%的场景。Pushgateway只用来兜底,比如作业启动阶段或者临时任务。
4.6 本章知识体系
下面这张图梳理了四种指标采集方式的关系与数据流向:
从图里可以看得很清楚:Flink内置指标是数据源头,四种采集方式各有各的出口。选型时不要贪多,根据你的基础设施和作业类型来定。