Flink 自定义 Failure Enricher:把失败“打标签”,让告警、归因、统计更聪明

1、它解决什么问题?

FailureEnricher 的典型用途:

  • 故障分类/归因 :给失败贴上 type=Systemtype=Usercomponent=Kafkareason=AuthFailed 等标签
  • 告警路由:不同标签推送到不同 oncall(平台组/业务组/中间件组)
  • 可观测性增强:把标签送到外部系统(Prometheus/OTel/自研平台)做统计报表
  • 联动通知 :在 processFailure() 里调用外部通知系统(注意:建议异步且要兜底超时)

触发时机:

  • 每次 JobManager 在运行时收到异常报告时都会触发 FailureEnrichers
  • Enricher 可以 异步 返回 labels(CompletableFuture<Map<String,String>>

2、插件结构与加载方式(重点)

2.1 你要实现的 3 件事

  1. 实现 FailureEnricher
  2. 实现 FailureEnricherFactory
  3. 使用 Java SPI 注册工厂:
    META-INF/services/org.apache.flink.core.failure.FailureEnricherFactory

然后把 jar 放到 Flink plugins/ 下的某个目录,例如:

text 复制代码
$FLINK_HOME/plugins/
  failure-enrichment/
    my-failure-enricher.jar

2.2 关键约束:output keys 必须唯一

每个 FailureEnricher 都要声明自己可能输出的 key 集合(getOutputKeys())。
所有 enrichers 的 key 集合必须互不重叠 ,否则有重叠 key 的 enrichers 会被忽略 (直接不生效)。

实践建议:统一加前缀,例如 fe.org.

  • fe.type
  • fe.component
  • fe.owner
  • fe.ticket

3、最小可用示例(可直接改成你们的规则)

3.1 Factory

java 复制代码
public class CustomFailureEnricherFactory implements FailureEnricherFactory {
   @Override
   public FailureEnricher createFailureEnricher(Configuration conf) {
        return new CustomEnricher(conf);
   }
}

3.2 Enricher(示例:按异常类型简单分类)

java 复制代码
public class CustomEnricher implements FailureEnricher {
    private final Set<String> outputKeys;

    public CustomEnricher(Configuration conf) {
        this.outputKeys = Set.of("fe.type", "fe.component");
    }

    @Override
    public Set<String> getOutputKeys() {
        return outputKeys;
    }

    @Override
    public CompletableFuture<Map<String, String>> processFailure(Throwable cause, Context context) {
        return CompletableFuture.supplyAsync(() -> {
            Map<String, String> labels = new HashMap<>();

            String msg = String.valueOf(cause.getMessage());
            labels.put("fe.type", "System");

            if (msg.contains("org.apache.kafka") || msg.contains("Sasl") || msg.contains("Kafka")) {
                labels.put("fe.component", "Kafka");
            } else if (msg.contains("org.apache.hadoop") || msg.contains("hdfs")) {
                labels.put("fe.component", "HDFS");
            } else {
                labels.put("fe.component", "Unknown");
            }

            return labels;
        });
    }
}

生产建议:这里的异步线程池别用默认 ForkJoinPool,最好用你自己可控的 executor,并设置超时/熔断,避免 enrichment 本身成为压力源。

3.3 SPI 文件内容

文件路径:

text 复制代码
META-INF/services/org.apache.flink.core.failure.FailureEnricherFactory

文件内容(一行一个工厂类名):

text 复制代码
com.yourcompany.flink.failure.CustomFailureEnricherFactory

4、配置:不配就不会启动

JobManager 启动时加载 FailureEnricher 插件,但 是否启用由配置决定:

properties 复制代码
jobmanager.failure-enrichers = com.yourcompany.flink.failure.CustomEnricher

注意点:

  • 如果 jobmanager.failure-enrichers 为空:不会启动任何 enricher
  • 配置的是 FailureEnricher 的类名(按你给的示例是这样写的),确保与实际类一致

5、如何验证它是否生效?

5.1 看 JobManager 日志

启动时会出现类似日志:

text 复制代码
Found failure enricher com.xxx.CustomEnricher at jar:file:/path/to/flink/plugins/failure-enrichment/xxx.jar!/...

5.2 看 REST API 输出的 failureLabels

从 JobManager REST API 查询时,会出现:

json 复制代码
"failureLabels": {
  "fe.type": "System",
  "fe.component": "Kafka"
}

你们可以用这个字段做:

  • 告警系统的规则匹配
  • 失败原因的聚合统计(按 label 分组)
  • 自助排障页的"失败类型"展示

6、生产落地建议(少踩坑)

  • label key 规范化:统一前缀 + 固定枚举值,避免团队各写各的导致不可聚合
  • 异步要可控:线程池、超时、异常兜底(enricher 失败不应影响主流程)
  • 避免重 IO/外部依赖:如要调用外部系统,务必做熔断/缓存/降级(否则故障时雪上加霜)
  • 和 Metrics/Event/Trace 打通 :failureLabels 很适合与 structured logging 的 flink-job-id 一起作为关联维度
相关推荐
代码匠心1 天前
从零开始学Flink:Flink SQL四大Join解析
大数据·flink·flink sql·大数据处理
武子康3 天前
大数据-242 离线数仓 - DataX 实战:MySQL 全量/增量导入 HDFS + Hive 分区(离线数仓 ODS
大数据·后端·apache hive
SelectDB4 天前
易车 × Apache Doris:构建湖仓一体新架构,加速 AI 业务融合实践
大数据·agent·mcp
武子康4 天前
大数据-241 离线数仓 - 实战:电商核心交易数据模型与 MySQL 源表设计(订单/商品/品类/店铺/支付)
大数据·后端·mysql
IvanCodes4 天前
一、消息队列理论基础与Kafka架构价值解析
大数据·后端·kafka
武子康5 天前
大数据-240 离线数仓 - 广告业务 Hive ADS 实战:DataX 将 HDFS 分区表导出到 MySQL
大数据·后端·apache hive
字节跳动数据平台6 天前
5000 字技术向拆解 | 火山引擎多模态数据湖如何释放模思智能的算法生产力
大数据
武子康6 天前
大数据-239 离线数仓 - 广告业务实战:Flume 导入日志到 HDFS,并完成 Hive ODS/DWD 分层加载
大数据·后端·apache hive
字节跳动数据平台7 天前
代码量减少 70%、GPU 利用率达 95%:火山引擎多模态数据湖如何释放模思智能的算法生产力
大数据
得物技术7 天前
深入剖析Spark UI界面:参数与界面详解|得物技术
大数据·后端·spark