Log4j2异步日志背后的数字

本文探讨了Apache Log4j2的同步、AsyncAppender异步和AsyncLogger异步日志打印方式的性能差异。通过压力测试,发现异步方式在CPU利用率、内存使用、磁盘写速度和接口TPS等方面优于同步方式,特别是AsyncLogger在多Appender场景下性能更优。同时,关闭immediateFlush参数对性能影响较小。
摘要由CSDN通过智能技术生成

作者:京东集团-京东零售-技术与数据中台-共享技术部-流量技术组 王丽。

引言

在程序开发过程中,几乎任何一个应用程序都会通过打印日志来记录跟踪程序运行情况,打印日志信息不仅可以让我们详细的了解程序内部的运行情况,更能在排查问题是提供详细的异常信息,为我们解决问题提供重要的线索。

最近在梳理项目运行情况时发现有个应用每天的日志量较大,在高峰时打印日志较为密集,发现配置日志打印使用的是Apache log4j2同步方式,那果断换成log4j2异步方式啊。但是都说异步方式打印日志性能好,强大且高效,具体性能可以提升多少,和同步方式相比差距有多大,为何大家更偏爱异步日志,今天通过数据对比,揭秘一下真实的原因。

log4j2的三种打印日志方式

Apache log4j2有三种打印日志方式,分别是同步方式、AsyncAppender异步及AsyncLogger异步方式,接下来分别针对这三种方式的用法进行简单的介绍。

1、Sync同步方式

同步记录日志是指当输出日志时,必须等待日志输出语句执行完毕后,才能执行后面的业务逻辑语句。

在输出日志时,会将日志信息转换为日志事件LogEvent对象,然后将LogEvent对象传入对应的Appender中,由对应的Appender调用appender()方法将日志信息写入文件。

下面的代码是在LogConfig类中的log()方法中,创建LogEvent对象,调用processLogEvent()方法将LogEvent对象传入对应的Appender中。

publicvoid log(final String loggerName, final String fqcn, final Marker marker, final Level level,

        final Message data, final Throwable t) {

    List<Property> props = null;

    if (!propertiesRequireLookup) {

        props = properties;

    } else {

        // 省略部分代码

    }

    final LogEvent logEvent = logEventFactoryinstanceof LocationAwareLogEventFactory ?

        ((LocationAwareLogEventFactory) logEventFactory).createEvent(loggerName, marker, fqcn, requiresLocation() ?

            StackLocatorUtil.calcLocation(fqcn) : null, level, data, props, t) :

        logEventFactory.createEvent(loggerName, marker, fqcn, level, data, props, t);

    try {

        log(logEvent, LoggerConfigPredicate.ALL);

    } finally {

        ReusableLogEventFactory.release(logEvent);

    }

}

protectedvoid log(final LogEvent event, final LoggerConfigPredicate predicate) {

    if (!isFiltered(event)) {

        processLogEvent(event, predicate);

    }

}

privatevoid processLogEvent(final LogEvent event, final LoggerConfigPredicate predicate) {

    event.setIncludeLocation(isIncludeLocation());

    if (predicate.allow(this)) {

        callAppenders(event);

    }

    logParent(event, predicate);

}

protectedvoid callAppenders(final LogEvent event) {

    final AppenderControl[] controls = appenders.get();

    //noinspection ForLoopReplaceableByForEach

    for (inti = 0; i < controls.length; i++) {

        controls[i].callAppender(event);

    }

}

在抽象类AbstractOutputStreamAppender中的appender()方法,最后调用directEncodeEvent()将日志信息写入文件。

/**

 * Actual writing occurs here.

 * <p>

 * Most subclasses of <code>AbstractOutputStreamAppender</code> will need to override this method.

 * </p>

 *

 * @param event The LogEvent.

 */

@Override

publicvoid append(final LogEvent event) {

    try {

        tryAppend(event);

    } catch (final AppenderLoggingException ex) {

        error("Unable to write to stream " + manager.getName() + " for appender " + getName(), event, ex);

        throwex;

    }

}

privatevoid tryAppend(final LogEvent event) {

    if (Constants.ENABLE_DIRECT_ENCODERS) {

        directEncodeEvent(event);

    } else {

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值