排查 Flink 日志输出文件不正确

Flink 默认日志框架

从 flink 官网 直接下载二进制 Flink tar 包,解压缩之后,查看 conf 目录和 lib 目录结构。
conf 目录结构如下:

-rwxr-xr-x@  1 zhangguanghui  staff  2138 12 11 20:39 log4j-cli.properties
-rwxr-xr-x@  1 zhangguanghui  staff  1884 12 11 20:39 log4j-console.properties
-rwxr-xr-x@  1 zhangguanghui  staff  1709 12 11 20:39 log4j-yarn-session.properties
-rwxr-xr-x@  1 zhangguanghui  staff  1939 12 11 20:39 log4j.properties
-rwxr-xr-x@  1 zhangguanghui  staff  2294 12 11 20:39 logback-console.xml
-rwxr-xr-x@  1 zhangguanghui  staff  1550 12 11 20:39 logback-yarn.xml
-rwxr-xr-x@  1 zhangguanghui  staff  2331 12 11 20:39 logback.xml

lib 目录结构如下:

-rwxr-xr-x@  1 zhangguanghui  staff  93195847 12 15 11:31 flink-dist_2.11-1.7.1.jar
-rwxr-xr-x@  1 zhangguanghui  staff    141914 12 15 11:28 flink-python_2.11-1.7.1.jar
-rwxr-xr-x@  1 zhangguanghui  staff  36059569 12 15 10:58 flink-shaded-hadoop2-uber-1.7.1.jar
-rwxr-xr-x@  1 zhangguanghui  staff    489884  3  1  2018 log4j-1.2.17.jar
-rwxr-xr-x@  1 zhangguanghui  staff      9931 12 13 18:17 slf4j-log4j12-1.7.15.jar

从 conf 中可以看出,flink 提供了两种日志框架配置文件,分别是 logback 和 log4j;但是通过 lib 下面的 log4j + slf4j-log4j12 可以看出,flink 默认提供的是 sfl4j + slf4j-log4j12 + log4j 日志框架组合。

slf4j 基础概念

slf4j 默认提供一组易用的打日志 API,用户可以通过 slf4j 和 slf4j 桥接器将日志传递给具体日志框架,例如 logback, log4j, log4j2,以下就是多种 slf4j 桥接器。


slf4j 桥接器

那么问题就来了,如果 JVM classpath 中包含多个桥接器和日志框架的话,slf4j 该如何选择?

slf4j 如何选择桥接器

要想知道 slf4j 选择了哪个桥接器,第一是要找到 slf4j 的桥接日志。如果是 flink on yarn 的话,桥接器日志在 taskmanager.err 日志中。

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/data00/yarn/nmdata/usercache/tiger/appcache/application_1546484418433_5098/filecache/12/device_report_flink-1.0.0.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/data08/yarn/nmdata/filecache/125/lib/slf4j-log4j12-1.7.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/data00/tiger/yarn_deploy/hadoop-2.6.0-cdh5.4.4/share/hadoop/common/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]

从日志中,我们看到 slf4j 找到了多个桥接器实现类,但是最终选择了 logback。一旦 slf4j 确认了桥接器之后,就会继续寻找对应的配置文件来初始化 Logger 框架,即 logback.xml 或者 log4j.properties。
如果 slf4j 选择的是 logback,而你没有相应的 logback.xml 配置文件的话,则 logback 将采用默认方式,将日志输出到 stdout。
如果 sfl4j 选择的是 log4j.properites,而你没有相应的 log4j.properties 而配置文件的话,则 log4j 将采用默认方式,将日志输出到 stdout 中。
总结,一般出问题在两点

  • 用户误将 logback-classic + logback-core 打进 user jar 中,使得 flink slf4j 桥接到 logback,但是却并为提供正确的 logback.xml。
    -用户自己代码中的 resources 目录中,误将 debug 的 log4j.properties 文件带入,覆盖了 conf 下面的 log4j.properties,导致 log4j 初始化不符合预期。

如何彻底解决问题

假如我们使用 slf4j + slf4j-log4j12+log4j 作为 flink 的日志框架,配置文件采用 conf/log4j.properties。
则用户 pom.xml 文件中的 maven shard plugin 应该如下配置


 
  org.apache.maven.plugins
  maven-shade-plugin
  3.0.0
  
   
   
    package
    
     shade
    
    
     
      
       org.slf4j:*
       log4j:*
       ch.qos.logback:*
      
     
     
      
      *:*
       
        log4j.properties
       
      
     
     
      
       com.bytedance.data.StreamingJob
      
     
    
   
  
 

其中

       ch.qos.logback:*

将用户端 logback 对应 jar 包移除。

log4j.properties

将用户端的 log4j.properties 移除

你可能感兴趣的:(排查 Flink 日志输出文件不正确)