Spark升级中对log4j中的一些思考

news/2024/7/5 23:55:28 标签: spark, log4j, 大数据

背景

最近在做Spark版本的升级(由spark3.1升级到spark3.5),其实单纯从spark升级涉及到的log4j来说,并没有什么能够记录的,
但是由于公司内部做了Spark的serveless,把spring和spark混在了一起,所以导致了不可预见的问题

分析

我们Spring用的是5.2.6.RELEASE版本,由于spark用的是logback作为日志的具体实现,而Spark在3.1和spark 3.5是采用了不同的日志具体实现:
spark3.1中采用的是log4j1 (log4j + slf4j-log4j2),spark 3.5中采用的是log42(log4j-core + log4j-api + log4j-slf4j2-impl),
再加上由于其他log包引入,比如说:

1. "org.apache.logging.log4j" % "log4j-1.2-api"

2. "org.apache.logging.log4j" % "log4j-to-slf4j"

3. "org.slf4j" % "slf4j-log4j12"

4. "org.slf4j" % "slf4j-api"

5. "org.slf4j" % "jcl-over-slf4j"

6. "org.slf4j" % "jul-to-slf4j"

7. "commons-logging" % "commons-logging"

8. "ch.qos.logback" % "logback-classic"

9. "ch.qos.logback" % "logback-core"

这真是太酸爽了,一时间几乎日志系统都齐全了,出现的错误也是千奇百怪:

1. Getting Exception org.apache.logging.slf4j.SLF4JLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext

2. java.lang.StackOverflowError at org.apache.logging.log4j.util.StackLocator.getCallerClass

3. Slf4j: Found slf4j-api dependency but no providers were found

4. java.lang.AssertionError: unsafe symbol Level (child of package log4j) in runtime reflection universe
        at scala.reflect.internal.Symbols$Symbol.<init>(Symbols.scala:224)
        at scala.reflect.internal.Symbols$TypeSymbol.<init>(Symbols.scala:3070)
        at scala.reflect.internal.Symbols$ClassSymbol.<init>(Symbols.scala:3261)
        at scala.reflect.internal.Symbols$StubClassSymbol.<init>(Symbols.scala:3539)

这些问题一度让我认为是Spark scala版本升级导致的(当然也是我在其中排除了各种乱七八糟的log包导致的问题),以上问题在google中也能搜寻到,
但是最后反思了一下:还是对log sl4j logback理解的不够:

  1. slf4j 原理及使用原则,可以参考slf4j 原理及使用原则
    这里面讲述了slf4j的一些原理以及关系
  2. 常用日志框架(Log4j,Slf4j,Logback)之间到底有啥区别 可以参考 常用日志框架(Log4j,Slf4j,Logback)之间到底有啥区别
    这里面讲了logback与其中的关系
  3. Difference between slf4j-log4j12 and log4j-slf4j-impl,可以参考Difference between slf4j-log4j12 and log4j-slf4j-impl
    这里讲了slf4j1.x slf4j2.x与Log4j 2.x Log4j 1.2的jar包的关系
  4. 秒懂log4j1与log4j2的区别,参考秒懂log4j1与log4j2的区别
    这里最为关键:
     slf4j的成功在于他的高屋建瓴,俯视一切。slf4j是日志门面(像:java的接口,没有提供任何实现),通过提供各种桥接器,适配各种日志框架(log4j1,logback等)。log4j1并没有这样的高度,于是log4j2就借鉴了slf4j的设计,log4f2有两部分组成:log4j-api、log4j-core。log4j-api和slf4j是相同的,都是日志门面,log4j-core是对log4j-api的实现,和log4j1、logback是相同的, 并且通过桥接器log4j-api还可以适配其他的日志系统(logback等)。这样log4j2就成了一个文堪比slf4,武可斗logback的双优生
    
    这里说明可以用log4j-api 适配logback,再加上极客时间的讨论:
     Geek_58afe9 问:
      
     "其实,我们只是换成了 Log4j2 API,真正的日志记录还是走的 Logback 框架。没错,这就是 SLF4J 适配的一个好处。". Log4j2 和 LogBack 不是同质化产品吗, Log4j2 api 怎么会走到Logback?
     作者回复: log4j2 API,并不是log4j 你在ch.qos.logback.classic.Logger.buildLoggingEventAndAppend设一个断点看一下整个过程就知道了,或者直接访问 https://github.com/JosephZhu1983/java-common-mistakes/blob/master/src/main/java/org/geekbang/time/commonmistakes/logging/placeholder/log4j2api_to_slf4j_to_logack.jpg 查看```
    
    
    
    

从以上我们知道 log4j2 不仅仅可以和slf4j适配,也可以和logback适配,这提供了另一条思路:不要只考虑slf4j和log4的爱恨情仇,也得考虑log4j和logback的亲密关系

解决

最终我们只留下了log4j2 (log4j-core + log4j-api) + logback (logback-classic + logback-core) ,其他的都排除掉,web端打包加编译没有任何问题,一切还是那么的美好(毕竟花了一天时间)

其他


http://www.niftyadmin.cn/n/5220679.html

相关文章

强化学习中的“agent“

在强化学习中&#xff0c;"agent"&#xff08;智能体&#xff09;是指一个在环境中执行动作以达到某个目标的实体。强化学习是一种机器学习范式&#xff0c;其中智能体通过与环境的交互来学习最优的行为策略&#xff0c;以最大化累积的奖励信号。 以下是强化学习中 …

前端下载文件或者图片方式,window.open或者a标签形式

首先分别讲一下下载文件的方式都有哪些 1.通过a标签的方式下载文件 <a href"http://www.baidu.com" download"baidu.html">下载</a> 我们点击下载&#xff0c;发现是跳转到了百度的首页&#xff0c;并没有真的下载文件。 因为a标签下载只能…

【数据结构初阶(5)】链式队列的基本操作实现

文章目录 队列的定义初始化队列队尾入队列队头出队列取队头元素取队尾元素获取队列有效元素个数判断队空销毁队列 因为队列比较简单&#xff0c;关于队列的概念就不过多赘述了&#xff0c;本文只讲链队的基本操作实现 队列的定义 定义队列结点结构 链队中的每个结点都应该包…

15 网关实战: 微服务集成Swagger实现在线文档

上节介绍了网关层面聚合API文档,通过网关的路由信息找到了各个服务的请求地址,这节讲一下微服务如何集成Swagger。 网关的API文档默认调用的是微服务的**/v2/api-docs**这个接口获取API详细信息,比如文章服务的URL:http://localhost:9000/blog-article/v2/api-docs,返回信…

Linux(10):Shell scripts

什么是 Shell scripts shell script&#xff08;程序化脚本&#xff09;&#xff1a;shell 部分是一个文字接口下让我们与系统沟通的一个工具接口&#xff1b;script 是脚本的意思&#xff0c;shell script 就是针对 shell 写的脚本。 shell script 是利用 shell 的功能所写的…

React Router React Reducer Hook 实现路由管理

一、概述 本文将通过React Router & React Redux实现登录和授权路由功能&#xff0c;将会从以下三个部分入手。 二、技术实现 auth-action-reducer (redux配置) export const Login (username, password) > ({type: login,username: username,password: password };…

跨标签页通信的8种方式(下)

跨标签页通信是指在浏览器中的不同标签页之间进行数据传递和通信的过程。在传统的Web开发中&#xff0c;每个标签页都是相互独立的&#xff0c;无法直接共享数据。然而&#xff0c;有时候我们需要在不同的标签页之间进行数据共享或者实现一些协同操作&#xff0c;这就需要使用跨…

【SA8295P 源码分析 (四)】134 - Android 侧 NFS Client 挂载 QNX NFS Server 目录不成功 问题排查方法

【SA8295P 源码分析】134 - Android 侧 NFS Client 挂载 QNX NFS Server 目录不成功 问题排查方法 一、QNX侧1. 检查镜像是否挂载成功&#xff1a;/mnt/nfs_shared_dir 目录2. 检查 /mnt/etc/exports 文件配置是否正确3. 检查 nfsd、rpcbind 两个服务程序是否在后台工作正常 二…