06、log4j2(日志实现框架)(二)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 06、log4j2(日志实现框架)(二)

四、异步日志


4.1、介绍异步日志


简单介绍

官网(Log4j2异步日志):https://logging.apache.org/log4j/2.x/manual/async.html


log4j2最大的特点就是异步日志,通过使用异步日志能够大大提升性能!


log4j2中提供了两种方式使用异步日志:AsyncAppender方式以及AsyncLogger方式。


其中AsyncLogger可以使用全局异步也可以是混合异步。


同步与异步区别

看下同步日志与异步日志之间的区别:


同步日志:



异步日志:



区别介绍:


对于同步日志操作,先进行Logger中的操作并传输到LogEvent对象中接着再执行Appender操作进行日志输出,主线程会将这些步骤都执行完才算作一条日志结束。

对于异步日志操作,我们可以看到主线程当执行完Logger操作产生出LogEvent对象会放置到一个队列后就结束返回,对应在队列中的LogEvent会交由线程2操作,大大提升了效率。


性能比对

我们再看下官网提供的一个性能图比对图:



主要看64threads的性能表现对比特别突出:


第一个是使用AsyncLogger方式的全局异步,性能最高。

第二个是使用AsyncLogger方式的混合异步,性能会稍差全局异步。

第三个是使用AsyncAppender方式性能与Log4j、Logback都差不多了。


4.2、依赖jar包


引入对应依赖jar包即可使用log4j2的异步日志:


<!--    log4j2并发编程依赖包   -->
<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.3.4</version>
</dependency>


若是日志使用的是slf4j+log4j2,并使用log4j2的异步日志,直接引入如下依赖


 

<!--使用slf4j作为日志的门面,使用log4j2来记录日志 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.30</version>
    </dependency>
    <!--为slf4j绑定日志实现 log4j2的适配器 -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>2.10.0</version>
    </dependency>
    <!--    Log4j2 门面API    -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.13.3</version>
    </dependency>
    <!--    Log4j2的日志实现   -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.11.1</version>
    </dependency>
    <!--    log4j2并发编程依赖包   -->
    <dependency>
        <groupId>com.lmax</groupId>
        <artifactId>disruptor</artifactId>
        <version>3.3.4</version>
    </dependency>
</dependencies>



4.3、异步日志的实际使用(3种)


①AsyncAppender方式

使用AsyncAppender是设置指定的一个appender为异步方式,如下:


<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug" monitorInterval="5">
    <properties>
        <property name="LOG_HOME">D:/logs</property>
    </properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n" />
        </Console>
        <!--   ①AsyncAppender方式 引用配置的appender    -->
        <Async name="Async">
            <AppenderRef ref="Console"/>
        </Async>
    </Appenders>
    <Loggers>
        <Root level="trace">
            <!--   ②引用name为Async的AsyncAppender方式    -->
            <AppenderRef ref="Async" />
        </Root>
    </Loggers>
</Configuration>


在Appenders标签中使用Async标签(引用想要进行异步日志的appender),最后将下面对应的RootLogger引用该异步Appender即可。

这种方式不太建议使用,因为其效率与logback差不多,并且日志输出时不显示行号。



②AsyncLogger方式

介绍


AsyncLogger才是log4j2的重头戏,也是官方推荐的异步方式。它可以使得调用Logger.log返回的 更快。你可以有两种选择:全局异步和混合异步。


全局异步则是让所有的日志都是异步的操作。

混合异步的话能够指定某个Appender进行异步,某个进行同步,更加灵活。


全局异步

全局异步就是所有的日志都是异步的操作,如何才能让所有的日志进行异步操作呢?我们只需要额外添加一个配置文件log4j2.component.properties并将其放置到resource目录下(Maven项目),配置内容如下:


Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector



之后我们运行项目默认所有的日志都是异步的操作,需要注意打印的日志消息没有行号!!!



混合异步(含自定义logger)

在原本log4j2.xml配置文件中自定义logger对象设置为异步(不需要添加全局异步的配置文件)


log4j2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!--日志框架本身日志等级debug  可以打印配置信息-->
<Configuration status="debug" monitorInterval="5">
    <properties>
        <property name="LOG_HOME">D:/logs</property>
    </properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n" />
        </Console>
    </Appenders>
    <Loggers>
        <!--***************************************************-->
        <!--   自定义Logger对象(异步)
               includeLocation="false" 表示关闭日志记录的行号信息
               additivity="false"  不继承rootLogger对象
        -->
        <AsyncLogger name="xyz.changlu" level="trace"
                     includeLocation="false" additivity="false">
            <AppenderRef ref="file"/>
        </AsyncLogger>
        <!--***************************************************-->
        <Root level="trace">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>



在<Loggers>标签中定义了一个AsyncLogger标签表示异步Logger,并且指定引用Appender。

这里配置RootLogger是同步的,自定义Logger是异步。


测试程序:


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Log4j2Test {
    //获取Logger实例
    public static final Logger LOGGER = LoggerFactory.getLogger(LogTest.class);
    public static void main(String[] args) {
        System.out.println(LOGGER.getName());//xyz.changlu.LogTest
        //1、打印日志记录
        LOGGER.error("error");
        LOGGER.warn("warn");
        LOGGER.info("info");
        LOGGER.debug("debug");
        LOGGER.trace("trace");
        //2、占位符输出
        String name = "changlu";
        int age = 20;
        LOGGER.info("报错,name:{},age:{}",name,age);
        //3、打印堆栈信息
        try {
            int i = 5/0;
        }catch (Exception e){
            LOGGER.error("报错",e);
        }
    }
}



使用这种方式的日志打印没有行号输出!!!


4.4、注意点


使用异步日志时的注意点如下:


使用异步日志时,打印的日志信息不会显示行号!

如果使用异步日志,AsyncAppender、AsyncLogger和全局日志,不要同时出现。否则性能会和 AsyncAppender一致,降至最低。

设置includeLocation=false ,打印位置信息会急剧降低异步日志的性能,比同步日志还要慢。


五、Log4j2的无垃圾模式介绍


垃圾收集暂停是延迟峰值的常见原因,并且对于许多系统而言,则需要花费更多大量精力来控制这些暂停。


许多日志库(包括以前版本的Log4j)在稳态日志记录期间分配临时对象,如日志事件对象,字符串, 字符数组,字节数组等。


这会对垃圾收集器造成压力并增加GC暂停发生的频率。


从版本2.6开始,默认情况下Log4j以“无垃圾”模式运行,其中重用对象和缓冲区,并且尽可能不分配临时对象。还有一个“低垃圾”模式,它不是完全无垃圾,但不使用ThreadLocal字段。


Log4j 2.6中的无垃圾日志记录部分通过重用ThreadLocal字段中的对象来实现,部分通过在将文本转换为字节时重用缓冲区来实现。



看下面两个版本的测试比较


使用Log4j 2.5:内存分配速率809 MB /秒,141个无效集合:



Log4j 2.6没有分配临时对象:0(零)垃圾回收:



通过使用无垃圾模式,我们可以看到GC收集数为0,并且每秒分配率为1.58MB/s。



避免创建临时对象机制的两个属性


有两个单独的系统属性可用于手动控制Log4j用于避免创建临时对象的机制:


log4j2.enableThreadlocals - 如果“true”(非Web应用程序的默认值)对象存储在ThreadLocal字段中并重新使用,否则将为每个日志事件创建新对象。

log4j2.enableDirectEncoders - 如果将“true”(默认)日志事件转换为文本,则将此文本转换 为字节而不创建临时对象。注意: 由于共享缓冲区上的同步,在此模式下多线程应用程序的同步日志记录性能可能更差。如果您的应用程序是多线程的并且日志记录性能很重要,请考虑使用异步记录器。


总结


1、Log4j2有6个日志等级,默认日志等级为error。—见第1部分


2、可设置定义配置文件log4j2.xml,包含了各个常使用的Appender以及RootLogger配置。—见第2部分


3、Log4j2也有日志门面,不过建议使用slf4j日志门面来对日志实现框架进行同一管理。—见第3部分


4、Log4j2也推出异步日志,其包含AsyncAppender方式、AsyncLogger方式((全局异步、混合异步))两种方式配置,其中全局异步日志性能最好大约是Logback的18倍,其次就是混合异步,性能最差的是AsyncAppender方式与Logback性能几乎差不多。使用异步日志需要注意的是其无法输出方法中的行号信息!—见4部分


5、在Log4j2的2.6版本之后使用无垃圾模式,通过重用ThreadLocal字段中的对象以及文本转换为字节时重用缓冲区来大大减少内存的使用。—见第5部分

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
1月前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
279 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
9天前
|
监控 安全 Apache
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球广泛使用的Web服务器软件,支持超过30%的活跃网站。它通过接收和处理HTTP请求,与后端服务器通信,返回响应并记录日志,确保网页请求的快速准确处理。Apache日志分为访问日志和错误日志,对提升用户体验、保障安全及优化性能至关重要。EventLog Analyzer等工具可有效管理和分析这些日志,增强Web服务的安全性和可靠性。
|
19天前
|
存储 监控 安全
什么是事件日志管理系统?事件日志管理系统有哪些用处?
事件日志管理系统是IT安全的重要工具,用于集中收集、分析和解释来自组织IT基础设施各组件的事件日志,如防火墙、路由器、交换机等,帮助提升网络安全、实现主动威胁检测和促进合规性。系统支持多种日志类型,包括Windows事件日志、Syslog日志和应用程序日志,通过实时监测、告警及可视化分析,为企业提供强大的安全保障。然而,实施过程中也面临数据量大、日志管理和分析复杂等挑战。EventLog Analyzer作为一款高效工具,不仅提供实时监测与告警、可视化分析和报告功能,还支持多种合规性报告,帮助企业克服挑战,提升网络安全水平。
|
2月前
|
Java 程序员 API
Android|集成 slf4j + logback 作为日志框架
做个简单改造,统一 Android APP 和 Java 后端项目打印日志的体验。
128 1
|
1月前
|
存储 监控 安全
什么是日志管理,如何进行日志管理?
日志管理是对IT系统生成的日志数据进行收集、存储、分析和处理的实践,对维护系统健康、确保安全及获取运营智能至关重要。本文介绍了日志管理的基本概念、常见挑战、工具的主要功能及选择解决方案的方法,强调了定义管理目标、日志收集与分析、警报和报告、持续改进等关键步骤,以及如何应对数据量大、安全问题、警报疲劳等挑战,最终实现日志数据的有效管理和利用。
|
2月前
|
Python
log日志学习
【10月更文挑战第9天】 python处理log打印模块log的使用和介绍
42 0
|
2月前
|
数据可视化
Tensorboard可视化学习笔记(一):如何可视化通过网页查看log日志
关于如何使用TensorBoard进行数据可视化的教程,包括TensorBoard的安装、配置环境变量、将数据写入TensorBoard、启动TensorBoard以及如何通过网页查看日志文件。
264 0
|
2月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
314 3
|
3月前
|
Java
日志框架log4j打印异常堆栈信息携带traceId,方便接口异常排查
日常项目运行日志,异常栈打印是不带traceId,导致排查问题查找异常栈很麻烦。
|
4月前
|
XML Java Maven
log4j 日志的简单使用
这篇文章介绍了Log4j日志框架的基本使用方法,包括在Maven项目中添加依赖、配置`log4j.properties`文件以及在代码中创建和使用Logger对象进行日志记录,但实际打印结果中日志级别没有颜色显示。
log4j 日志的简单使用
下一篇
DataWorks