Flink 日志怎么用从“找得到”到“看得懂”,再到“可检索可关联”

1.1 日志文件来自哪些进程

Flink 的每个进程都会产生日志文件,例如:

  • JobManager(包含 Dispatcher、ResourceManager 等角色)
  • TaskManager
  • CLI / SQL Client / Session 启动脚本(yarn-session、kubernetes-session)

这些日志会记录进程生命周期内的大量事件,排查问题通常先看 WARN/ERROR,再回溯上下文。

1.2 从 Web UI 访问

你可以在 Flink Web UI 的 JobManager / TaskManager 页面直接打开日志(集群运行时最方便的入口)。

如果你运行在 YARN / Kubernetes 等资源管理平台,平台通常也会提供额外的日志入口(比如 YARN 的 container logs、K8s 的 kubectl logs + 日志采集系统)。

  • Flink 使用 SLF4J 作为日志接口(门面),这意味着你可以替换底层实现(Log4j2 / Logback 等)而不改 Flink 源码
  • 默认底层实现是 Log4j 2

这点很关键:你在集群里看到的最终日志格式/输出/滚动策略,主要由 Log4j2 配置决定,而不是 Flink 代码。

3、结构化日志(Structured Logging):用 MDC 把"作业维度"串起来

Flink 会往 MDC 里写一些字段(实验特性),最常用的是:

  • Job ID

    • key:flink-job-id
    • format:string(长度 32)

意义:

  • 在 JSON 日志或结构化采集(ELK/Opensearch/Loki/Splunk)里,你可以用 flink-job-id 快速过滤同一个 Job 的日志
  • 对比"同一个 TM 上跑多个作业"的场景,这个字段是最有效的切割维度之一

3.1 Log4j2 PatternLayout 示例(非 JSON)

你可以显式把 MDC 打出来,例如:

text 复制代码
[%-32X{flink-job-id}] %c{0} %m%n

效果就是每行日志前面带上 jobId,排查链路会舒服很多。

3.2 Log4j2 JsonTemplateLayout(推荐结构化)

如果你们有结构化日志平台,建议直接用 Log4j2 的 JsonTemplateLayout

  • 高性能、低 GC、模板可定制
  • Flink 发行包里已经包含 log4j-layout-template-json

落地建议:把 flink-job-id 做成 JSON 字段,并在日志平台建立索引/标签。

4、Log4j2 怎么配置:conf 目录里的 4 份"场景化配置"

Flink distribution 的 conf/ 目录默认提供这些 Log4j2 properties 文件,并且会自动在对应场景启用:

  • log4j-cli.properties:CLI(flink runsql-client 等)
  • log4j-session.properties:启动 Kubernetes/YARN session cluster 的 CLI
  • log4j-console.properties:JM/TM 前台运行(常见于 K8s 前台容器)
  • log4j.properties:JM/TM 默认使用

热更新:Log4j2 自动扫描配置变更

Log4j 会定期扫描 properties 文件并自动调整日志行为,默认 每 30 秒 扫描一次,由 monitorInterval 控制。

运维价值:

  • 线上临时调高某个 package 的日志级别,不必重启(但也要注意风险:日志量暴涨)

这些是 Flink 层面的日志配置入口(最终会影响 Log4j 的输出目录、级别、保留策略等):

  • env.log.dir:日志目录(必须是绝对路径),默认是 Flink home 下的 log 目录
  • env.log.level:Root logger level(默认 INFO)
  • env.log.max:最多保留多少个旧日志文件(默认 10)

落地建议:

  • 生产环境把 env.log.dir 指到挂载盘(避免容器文件系统撑爆)
  • env.log.max 配合你们的日志采集策略和磁盘容量一起定

6、替换日志实现:Log4j1 / Logback(能用但不建议优先)

6.1 Log4j1(兼容但需要你处理 classpath)

Flink 提供 Log4j API bridge 以兼容旧应用,但要真正用 Log4j1,你必须严格处理依赖:

  • 确保 Log4j2 相关核心实现不在 classpath
  • 把 Log4j1 与对应的 slf4j 绑定放进来
  • conf 下的配置文件也要换成 Log4j1 版本

一般只有历史包袱很重才这么做。

6.2 Logback

要用 Logback:

  • 移除 log4j-slf4j-impl

  • 加入 logback-corelogback-classic

  • 使用 conf 下的:

    • logback-session.properties
    • logback-console.properties
    • logback.xml

注意:Logback 1.3+ 需要 SLF4J 2,目前不支持(这条非常关键,别踩坑)。

7、开发者最佳实践:写对日志,线上才好查

7.1 Logger 定义方式(强烈建议)

java 复制代码
private static final Logger LOG = LoggerFactory.getLogger(Foobar.class);

7.2 用占位符,避免无意义的字符串拼接

java 复制代码
LOG.info("This message contains {} placeholders. {}", 2, "Yippie");

7.3 异常日志要把 exception 作为最后一个参数

java 复制代码
catch (Exception exception) {
  LOG.error("An {} occurred.", "error", exception);
}

落地收益:

  • 你不会丢堆栈(堆栈是排障的灵魂)
  • 避免无用的字符串构造,减少 GC 压力

8、实战排障:我一般怎么"用日志定位问题"

给你一个可复制的顺序(尤其适合生产应急):

  1. 先在日志平台/文件里按 ERROR / WARN 找"第一现场"

  2. 把时间窗口扩大到错误前后(例如前后 2~5 分钟)

  3. 如果启用了 MDC:用 flink-job-id 把同一作业日志过滤出来

  4. 分进程看:

    • JM:调度失败、Checkpoint 协调、资源申请、HA/选主、REST 操作
    • TM:反压、网络、状态/RocksDB、GC、连接器异常、算子异常
  5. 再回到 Web UI 看对应 Job/Vertex 的异常页与 subtask 分布,和日志时间对齐、

相关推荐
代码匠心1 天前
从零开始学Flink:Flink SQL四大Join解析
大数据·flink·flink sql·大数据处理
武子康2 天前
大数据-242 离线数仓 - DataX 实战:MySQL 全量/增量导入 HDFS + Hive 分区(离线数仓 ODS
大数据·后端·apache hive
SelectDB3 天前
易车 × Apache Doris:构建湖仓一体新架构,加速 AI 业务融合实践
大数据·agent·mcp
武子康4 天前
大数据-241 离线数仓 - 实战:电商核心交易数据模型与 MySQL 源表设计(订单/商品/品类/店铺/支付)
大数据·后端·mysql
IvanCodes4 天前
一、消息队列理论基础与Kafka架构价值解析
大数据·后端·kafka
武子康5 天前
大数据-240 离线数仓 - 广告业务 Hive ADS 实战:DataX 将 HDFS 分区表导出到 MySQL
大数据·后端·apache hive
字节跳动数据平台5 天前
5000 字技术向拆解 | 火山引擎多模态数据湖如何释放模思智能的算法生产力
大数据
武子康6 天前
大数据-239 离线数仓 - 广告业务实战:Flume 导入日志到 HDFS,并完成 Hive ODS/DWD 分层加载
大数据·后端·apache hive
字节跳动数据平台7 天前
代码量减少 70%、GPU 利用率达 95%:火山引擎多模态数据湖如何释放模思智能的算法生产力
大数据
得物技术7 天前
深入剖析Spark UI界面:参数与界面详解|得物技术
大数据·后端·spark