Flink原理:Flink中的日志框架配置

1. 背景

很多同学在进行Flink开发时,无论是使用log4j或log4j2,常常出现各种问题,如下图所示:
在这里插入图片描述今天我们就要拨开云雾见天日,聊聊日志相关的知识,搞清楚这些报错的原因。

众所周知,现代框架都是用门面模式进行日志输出,例如使用Slf4j中的接口输出日志,具体实现类需要由log4j,log4j2,logback等日志框架进行实现,如Flink的类中是这样输出日志的:

// org.apache.flink.api.java.ClosureCleaner

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Internal
public class ClosureCleaner {
	private static final Logger LOG = LoggerFactory.getLogger(ClosureCleaner.class);
...
}

这种设计使得用户可以自由地进行日志框架的切换。

2. 日志门面slf4j

slf4j全名Simple Logging Facade for Java,为java提供的简单日志Facade。Facade门面说白了就是接口。它允许用户以自己的喜好,在工程中通过slf4j接入不同的日志系统。slf4j入口就是众多接口的集合,它不负责具体的日志实现,只在编译时负责寻找合适的日志系统进行绑定。具体有哪些接口,全部都定义在slf4j-api中。查看slf4j-api源码就可以发现,里面除了public final class LoggerFactory类之外,都是接口定义。因此slf4j-api本质就是一个接口定义。要想使用slf4j日志门面,需要引入以下依赖

 <dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>1.7.25</version>
</dependency>

这个包只有日志的接口,并没有实现,所以如果要使用就得再给它提供一个实现了些接口的日志框架包,比如:log4j,log4j2,logback等日志框架包,但是这些日志实现又不能通过接口直接调用,实现上他们根本就和slf4j-api不一致,因此slf4j和日志框架之间又增加了一层桥接器来转换各日志实现包的使用,比如slf4j-log4j12,log4j-slf4j-impl等。

2.1 slf4j + log4j

Log4j + Slf4j的使用组合最为常见,依赖关系如下所示:
在这里插入图片描述
使用时要引入maven依赖:

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
2.2 slf4j + log4j2

但是Log4j目前已经停止更新了。Apache推出了新的Log4j2来代替Log4j,Log4j2是对Log4j的升级,与其前身Log4j相比有了显着的改进,并提供了许多Logback可用的改进,同时解决了Logback体系结构中的一些固有问题。因此,Log4j2 + Slf4j应该是未来的大势所趋。其依赖关系如下:
在这里插入图片描述
使用时要引入maven依赖:

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.9.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.9.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.9.1</version>
        </dependency>

无论是使用log4j还是log4j2,尤其要记得引入各自的桥接器,否在就会报文章开头找不到配置的错误!

3. 避免冲突

由于log4j2的性能优异且是大势所趋,本文决定使用log4j2作为Flink开发的日志框架,一切按照上文配置就绪,却在运行时抛出如下错误:
在这里插入图片描述
如报错所示,在classpath下发现了两个桥接器,很明显,有某个依赖间接依赖了log4j的桥接器slf4j-log4j12,使得classpath下同时存在了slf4j-log4j12log4j-slf4j-impl这两个桥接器,经过mvn dependency:tree -Dincludes=:slf4j-log4j12命令分析,我们找出了这个依赖,在其中将slf4j-log4j12进行了排除:

        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-redis_2.11</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
            <version>1.1.5</version>
        </dependency>

错误顺利消失,正当喜悦之时,有报出如下错误:
在这里插入图片描述
乍一看有些懵,不过仔细想想,刚刚排除了桥接器的冲突,这个问题是否是因为项目间接依赖了log4j,而导致底层日志框架log4j和log4j2产生了冲突呢?日志门面slf4j虽然正确找到了log4j2的桥接器log4j-slf4j-impl,但是接下来会不会又根据maven的短路优先原则,歪打正着地找到了log4j框架(log4j-slf4j-impl桥接器本应去寻找log4j2框架)?本文意图使用log4j2,因此配置了log4j2.xml,自然不会去配置log4j.properties,更无法找到log4j.properties中的appender等组件了。

果不其然,在找到并排除了间接依赖的log4j之后,错误也随之消失:

        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-redis_2.11</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
            <version>1.1.5</version>
        </dependency>

4. 总结

  1. 不管使用log4j还是log4j2,别忘了在pom.xml中配置桥接器!
  2. 使用一个日志框架时,请排除另一个日志框架所使用的一切直接和间接依赖,避免一些令人迷惑的报错!
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于Apache Flink的安装、配置和部署,可以按照以下步骤进行操作: 1. 安装Java:Flink是基于Java开发的,因此需要先安装Java运行环境。确保安装了适当版本的Java,并设置好JAVA_HOME环境变量。 2. 下载Flink:从Apache Flink的官方网站(https://flink.apache.org/)下载最新的二进制发布包。选择适合的版本,下载并解压缩到本地目录。 3. 配置Flink:进入Flink的安装目录,编辑conf/flink-conf.yaml文件,根据需要进行相应的配置。常见的配置项包括JobManager和TaskManager的内存大小、并行度、检查点设置等。 4. 启动Flink:在Flink的安装目录下,执行bin/start-cluster.sh(Linux/Mac)或bin/start-cluster.bat(Windows)命令来启动Flink集群。这将启动JobManager和TaskManager进程。 5. 验证安装:在浏览器访问http://localhost:8081,应该可以看到Flink Web UI的界面。这个界面提供了对Flink集群的监控和管理功能。 6. 编写和提交作业:使用Flink提供的API或者开发框架(如Apache Beam)编写作业。将作业打包成可执行的JAR文件,并使用bin/flink run命令提交作业到Flink集群。 7. 监控和管理:通过Flink Web UI监控作业的运行状态、性能指标和日志。可以通过bin/stop-cluster.sh(Linux/Mac)或bin/stop-cluster.bat(Windows)命令停止Flink集群。 以上是一个基本的安装、配置和部署Flink的流程,具体操作还需要根据实际需求和环境来进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值