一、问题背景
发现生产环境容器部署的应用打日志打的很猛,比如输出了很多sql的Info日志,然后我看我们开发环境的log4j2-spring.xml 修改日志级别,发现完全不生效。后面去看容器里面的部署发现容器里面的启动脚本会最后直接把日志输出到
....>dockerlog.txt
然后我们log4j2-spring.xml里面也有日志输出到另一个文件夹,这样就导致了两份日志重叠,很混乱。
二、解决问题
1、为什么标准输出里面还是打印了很多INFO的sql日志
因为我们的application.yml里面mybatis的日志配置的不对,没有配置log4j2的
这里需要修改下
mybatis-plus:configuration:#log-impl: org.apache.ibatis.logging.stdout.StdOutImpllog-impl: org.apache.ibatis.logging.log4j2.Log4j2Impl
这样就sql打印走的就是Log4j2了
2、为什么我配置的log4j2-spring.xml不生效
那是因为我启动的脚本把这个配置的读取放在了jar后面,应该放在jar的前面
#启动nohup java -Dlogging.config=file:./config/log4j2-spring.xml -jar \app.jar \--server.port=9103 \--spring.config.location=./config/application.yml &
这样就能读取我jar外面的xml了,如果放jar后面读取的将会是jar包里面的
3、容器里面的启动脚本会自行有日志怎么办?
我们发现用容器启动可能自己加了统一的日志,比如
....>dockerlog.txt
那我们的log4j2里面的日志就冲突了怎么办,我们可以只保留标准输出即可
<AsyncRoot level="info"><AppenderRef ref="STDOUT"/><!--<AppenderRef ref="RandomAccessFile"/>--></AsyncRoot>
下面的RandomAccessFile日志输出和自动备份的在容器环境就不进行了,以容器为准。
三、最佳实践
1、把springboot的配置和application.yml的配置都抽取出来不要用jar包里面的
启动脚本就改为下面
#! /bin/sh#killSERVER_NAME="app-1.0"pid=`ps -ef |grep java |grep -w $SERVER_NAME| grep -v grep | awk '{print $2}'`echo "run pid:"$pidif [ "$pid" != "" ]thenecho "Try to kill the SpringBoot service $SERVER_NAME progress $pid......"kill -9 $pidsleep 1fi#启动nohup java -Dlogging.config=file:./config/log4j2-spring.xml -jar \app-1.0.jar \--server.port=9000 \--spring.config.location=./config/application.yml &echo "end"
注意-Dlogging一定要放在jar前面才有效
2、application.yml文件中mybaitis的日志要交给log4j2管理
mybatis-plus:configuration:#log-impl: org.apache.ibatis.logging.stdout.StdOutImpllog-impl: org.apache.ibatis.logging.log4j2.Log4j2Impl
3、log4j2-spring.xml若是非容器环境则放开RandomAccessFile
<?xml version="1.0" encoding="UTF-8"?><Configuration status="info" strict="true" name="LogConfig"><Properties><Property name="filepath">logs</Property></Properties><Appenders><Console name="STDOUT" target="SYSTEM_OUT"><PatternLayout><Pattern>[%d]-[%level]-[%t]-[%c]-[%method]-%msg%n</Pattern></PatternLayout></Console><Console name="STDOUTWARN" target="SYSTEM_OUT"><ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY" /><PatternLayout><Pattern>[%d]-[%level]-[%t]-[%c]-[%method]-%msg%n</Pattern></PatternLayout></Console><RollingRandomAccessFile name="RandomAccessFile"fileName="${filepath}/info.log"immediateFlush="false"filePattern="${filepath}/info.log-%d{yyyy-MM-dd}-%i.log.gz"><PatternLayout><Pattern>%d-[%level]-[%t]-[%c]-[%method]-%msg%n</Pattern></PatternLayout><Policies><OnStartupTriggeringPolicy/><TimeBasedTriggeringPolicy/><SizeBasedTriggeringPolicy size="200MB" /></Policies><!--保存日志文件个数--><DefaultRolloverStrategy max="400"/></RollingRandomAccessFile></Appenders><Loggers><!--有需要个性化定制<AsyncLogger name="com.xxx.xxx" level="info" additivity="false" includeLocation="true"><AppenderRef ref="STDOUT"/><AppenderRef ref="RandomAccessFile"/></AsyncLogger>--><AsyncLogger name="org.springframework.context.annotation.ConfigurationClassPostProcessor"level="ERROR" additivity="false" includeLocation="true"><AppenderRef ref="STDOUT"/><AppenderRef ref="RandomAccessFile"/></AsyncLogger><AsyncRoot level="info"><AppenderRef ref="STDOUT"/><AppenderRef ref="RandomAccessFile"/></AsyncRoot></Loggers></Configuration>
容器环境自己有日志管理则关闭
<AsyncRoot level="info"><AppenderRef ref="STDOUT"/><!--<AppenderRef ref="RandomAccessFile"/>--></AsyncRoot>
若是没有则跟开发测试一样。
4、pom.xml记得引入log4j2和异步日志
<!-- web框架 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.glassfish</groupId><artifactId>jakarta.el</artifactId></exclusion><!--排除本身的--><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><!--加上log4j2--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId></dependency><!--异步日志--><dependency><groupId>com.lmax</groupId><artifactId>disruptor</artifactId><version>3.4.0</version></dependency>
注:个人观点
