Logback 在 ECP 工程中的多线程使用指导
摘要:在 ECP(Enterprise Content Platform)工程中,Logback 是一个常用的日志管理框架,它提供了多线程日志记录的支持和自定义配置选项。下面是关于 Logback 多线程的两种方式使用
一、多线程日志记录支持
Logback具有良好的多线程支持,可以在多线程环境下安全地记录日志:
a. 线程安全性:Logback的核心组件(如Logger和Appender)是线程安全的,可以在多个线程中并发使用。
b. 异步日志记录:Logback提供了异步的日志记录功能,可以将日志事件缓存起来并在后台的线程中进行写入,以提高性能。通过配置异步Appender,你可以启用异步日志记录。
二、多线程日志记录方式
第一种、普通日志记录
每个线程独立拥有自己的 Logger 实例,可以方便地对每个线程的日志进行管理和记录。
每个线程创建自己的 Logger 实例,并使用不同的线程名称进行区分,这样可以确保每个线程的日志记录是相互隔离的。
代码示例
package cn.histo.desk.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author Verite
*/
public class AsyncLoggingThread implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(AsyncLoggingThread.class);
private static int counter = 0;
@Override
public void run() {
int threadId = ++counter;
logger.info("Thread {}: Logging message", threadId);
logger.info("Thread {}: Logging another message", threadId);
}
public static void main(String[] args) {
ThreadFactory threadFactory = Thread::new;
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 10, 30, TimeUnit.SECONDS, new SynchronousQueue<>(), threadFactory);
for (int i = 0; i < 6; i++) {
threadPoolExecutor.submit(new AsyncLoggingThread());
}
threadPoolExecutor.shutdown();
}
}
结果示例

以上方式保证了多线程记录日志相互隔离。如果想要日志有序输出请使用 synchronized AtomicInteger 等方式保证日志记录顺序
第二种、使用 AsyncAppender
Logback还提供了异步日志记录的功能,它可以在后台的线程中异步地写入日志,从而提高应用程序的性能。通过配置异步Appender,可以启用异步日志记录。
xml 配置代码
<!-- 生成日志文件 -->
<appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件输出的文件名 -->
<FileNamePattern>target/log/info-%d{yyyy-MM-dd}.log</FileNamePattern>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%n%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%logger{50}] %n%-5level: %msg%n</pattern>
</encoder>
<!-- 打印日志级别 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 异步处理 ,
queueSize=500,则discardingThreshold 的取值范围: 0 <= discardingThreshold <= 500。
discardingThreshold =0时,表示剩余容量在小于0%的时候,日志级别<=INFO的内容才不会打印;
但剩余容量最少也只会等于0%,不会小于0%,所以在此情况下所有日志级别都会打印。
discardingThreshold = 500时,表示剩余容量在小于100%的时候,
日志级别<=INFO的内容不会打印;所以此情况下只会打印WARN、ERROR级别的内容。
-->
<appender name="ASYNC_DATA" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>500</queueSize>
<appender-ref ref="INFO"/>
</appender>
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook">
<delay>1000</delay><!-- 延迟的时间,单位为毫秒 -->
</shutdownHook>
使用示例
<logger name="cn.histo.desk.controller.DemoFeignController" level="info" additivity="false">
<appender-ref ref="ASYNC_DATA"/>
</logger>
在上面的示例中,我们创建了一个名为ASYNC的异步Appender,并将它作为根Logger的Appender。此时,日志事件会被缓存起来,然后在后台的线程中异步地进行写入。
注意:shutdownHook 可以延迟关闭Logback的LoggerContext
,以便异步日志记录器有时间处理完所有的日志事件
这些方式提供了灵活且可靠的日志记录解决方案,使多线程应用中的日志记录更加准确和高效。根据实际需求和场景选择合适的方式来使用 Logback,以满足多线程环境下的日志需求。
三、多线程-疑问解答
1,什么是线程安全?
答:当多个线程同时访问或修改共享资源时,能够保证多个线程在使用或者修改共享资源后,共享资源是我们想要准确数据,此时我们就说是线程安全的。
2,logback 是如何保证线程安全的?
答: Logger和Apender两个组件的数据共享资源的状态保持一致,结果符合预期并准确
Logger 组件是依据数据结构ConcurrentHashMap,保证同时写入和修改时某个Logger的数据一致,并且在创建某个Logger时使用了synchronized 并且使用了双重判定,在put的时候保证创建Logger时的数据一致,如下图所示


Appender中的ConsoleAppender和FileAppender 组件 继承了OutputStreamAppender 是根据 输出字节流的writeBytes 方法 中的 ReentrantLock 锁定文件流 完成日志的输出。 如下图所示


3,假设现在有以下2个文件,DemoFeignController文件和 MyTest 文件,如果在MyTest文件中建立demoLogger消息记录器,记录的是MyTest信息,那么附加器是哪一个 ?
答:结果如图

参考资料
logback官方文档 https://logback.qos.ch/manual/
中文手册 https://www.docs4dev.com/docs/zh/logback/1.3.0-alpha4/reference/introduction.html
日志背景以及基础使用介绍 https://www.liaoxuefeng.com/wiki/1252599548343744/1264739155914176
lockback 日志基本使用介绍 https://blog.csdn.net/weixin_72518095/article/details/125574382
locak 日志实战介绍 https://blog.csdn.net/weixin_72518095/article/details/125707612
全部评论