0.背景
虽然大部分的java项目使用的都是logback,但是仍然有很多开源项目使用log4j,例如kafka、zookeeper。但是log4j已经于2012年停止更新,并且log4j扫出如下安全漏洞:
CVE-2020-9488
CVE-2019-17571
对于安全性要求高的公司,这种是不允许的,那么问题就是如何在不修改这些开源中间件源码的情况下解决这些CVE漏洞。
从log4j2的官网https://logging.apache.org/log4j/2.x/了解到,log4j和log4j2是存在一定的兼容性的,它们实现的都是SLF4J的API,理论上来说是可以通过替换jar包切换的。
1.log4j的jar包替换为log4j2
以zookeeper和kafka为例,删除lib目录下的这三个jar包:slf4j-log4j12、slf4j-api和log4j

引入log4j2的包:
log4j-1.2-api-2.13.2.jar
log4j-api-2.13.2.jar
log4j-core-2.13.2.jar
log4j-slf4j-impl-2.13.2.jar
slf4j-api-1.7.30.jar
尤其要注意log4j-1.2-api这个包,这个一定要引入,这是为兼容log4j 1.x提供的。本来使用log4j2框架是不需要这个包的,但是kafka中有些地方打印日志并不是用的SLF4J接口org.slf4j.Logger,有些地方直接使用了org.apache.log4j里的类。这就需要通过log4j-1.2-api这个包进行桥接。

这时候kafka运行没问题,zookeeper却报出了类找不到,org.apache.log4j.jmx.HierarchyDynamicMBean,难道就log4j换log4j2就凉在了zk这里?
仔细看zk的源码,这个是jmx开启才需要的,并且是通过类加载器去实例化的,并不是直接import的。

并且zk的jmx是有提供开关可以关闭的,也就是说我们在zk的启动参数里关掉jmx就不会去加载这个类了。将zookeeper.jmx.log4j.disable设置为true即可。

2.修改log4j配置
本来替换完jar包之后kafka和zookeeper进程都已经可以正常运行了,但是长时间运行后发现个很奇怪的现象,经常发现日志文件的最后一行内容只有一半,日志被截断了。。。
Log4j2的官网上有对log4j1.x兼容性的介绍:

除一些常用API的兼容外,还有配置方式也兼容了。不过这个“experimental”形容词就坑了呀。实验性的支持?也就说log4j1.x的配置并不能完全转换为log4j2的,能转到啥程度估计也很难说。
所以干脆直接将配置文件也切换成log4j2的配置方式,打印中断的问题就没有再出现了。例如kafka的log4j.properties修改为如下的配置:
status = error
dest = err
name = PropertiesConfig
property.filename = d:/kafka/log/server.log
property.stateChange.filename = d:/kafka/log/state-change.log
property.request.filename = d:/kafka/log/kafka-request.log
property.cleaner.filename = d:/kafka/log/log-cleaner.log
property.controller.filename = d:/kafka/log/controller.log
property.authorizer.filename = d:/kafka/log/kafka-authorizer.log
property.sasl.filename = d:/kafka/log/kafka-sasl.log
filter.threshold.type = ThresholdFilter
filter.threshold.level = debug
appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %m%n
appender.console.filter.threshold.type = ThresholdFilter
appender.console.filter.threshold.level = error
appender.rolling.type = RollingFile
appender.rolling.name = RollingFile
appender.rolling.fileName = ${
filename}
appender.rolling.filePattern = d:/kafka/log/server-%d{
yyyy-MM-dd}-%i.log.gz
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = %d %p %C{
1.}

本文介绍了如何在不改动开源项目源码的情况下,通过替换jar包和配置调整,将kafka和zookeeper中的log4j迁移到更安全的log4j2,包括处理CVE漏洞、配置文件转换和启动脚本修改。

4967

被折叠的 条评论
为什么被折叠?



