log4j2 異步日誌

Log4j2異步日誌

異步日誌

log4j2最大的特點就是異步日誌,其性能的提升主要也是從異步日誌中受益,我們來看看如何使用log4j2的異步日誌。

同步日誌

異步日誌

Log4j2提供了兩種實現日誌的方式,一個是通過AsyncAppender,一個是通過AsyncLogger,分別對應前面我們說的Appender組件和Logger組件。

注意:配置異步日誌需要添加依賴

<!--異步日誌依賴-->
<dependency>
	<groupId>com.lmax</groupId>
	<artifactId>disruptor</artifactId>
	<version>3.3.4</version>
</dependency>

1. AsyncAppender方式

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
	<properties>
		<property name="LOG_HOME">D:/logs</property>
	</properties>
	<Appenders>
		<File name="file" fileName="${LOG_HOME}/myfile.log">
			<PatternLayout>
				<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
			</PatternLayout>
		</File>
		<Async name="Async">
			<AppenderRef ref="file"/>
		</Async>
	</Appenders>
	<Loggers>
		<Root level="error">
			<AppenderRef ref="Async"/>
		</Root>
	</Loggers>
</Configuration

2. AsyncLogger方式

AsyncLogger纔是log4j2 的重頭戲,也是官方推薦的異步方式。它可以使得調用Logger.log返回的更快。你可以有兩種選擇:全局異步和混合異步。

全局異步就是,所有的日誌都異步的記錄,在配置文件上不用做任何改動,只需要添加一個log4j2.component.properties 配置;

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

混合異步就是,你可以在應用中同時使用同步日誌和異步日誌,這使得日誌的配置方式更加靈活。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
	<properties>
		<property name="LOG_HOME">D:/logs</property>
	</properties>
	<Appenders>
		<File name="file" fileName="${LOG_HOME}/myfile.log">
			<PatternLayout>
				<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
			</PatternLayout>
		</File>
		<Async name="Async">
			<AppenderRef ref="file"/>
		</Async>
	</Appenders>
	<Loggers>
		<AsyncLogger name="com.leon" level="trace" includeLocation="false" additivity="false">
			<AppenderRef ref="file"/>
		</AsyncLogger>
		<Root level="info" includeLocation="true">
			<AppenderRef ref="file"/>
		</Root>
	</Loggers>
</Configuration>

如上配置: com.leon日誌是異步的,root日誌是同步的。

使用異步日誌需要注意的問題:

1. 如果使用異步日誌,AsyncAppender、AsyncLogger和全局日誌,不要同時出現。性能會和AsyncAppender一致,降至最低。

2. 設置includeLocation=false ,打印位置信息會急劇降低異步日誌的性能,比同步日誌還要慢。

<?xml version="1.0" encoding="UTF-8"?>
<!--
    status="warn" 日誌框架本身的輸出日誌級別
    monitorInterval="5" 自動加載配置文件的間隔時間,不低於 5 秒
-->
<Configuration status="debug" monitorInterval="5">

    <!--
        集中配置屬性進行管理
        使用時通過:${name}
    -->
    <properties>
        <property name="LOG_HOME">/logs</property>
    </properties>

    <!--日誌處理-->
    <Appenders>
        <!--控制檯輸出 appender-->
        <Console name="Console" target="SYSTEM_ERR">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n" />
        </Console>

        <!--日誌文件輸出 appender-->
        <File name="file" fileName="${LOG_HOME}/myfile.log">
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n" />
        </File>

        <!--<Async name="Async">-->
            <!--<AppenderRef ref="file"/>-->
        <!--</Async>-->

        <!--使用隨機讀寫劉的日誌文件輸出 appender,性能提高-->
        <RandomAccessFile name="accessFile" fileName="${LOG_HOME}/myAcclog.log">
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n" />
        </RandomAccessFile>

        <!--按照一定規則拆分的日誌文件的 appender-->
        <RollingFile name="rollingFile" fileName="${LOG_HOME}/myrollog.log"
                     filePattern="/logs/$${date:yyyy-MM-dd}/myrollog-%d{yyyy-MM-dd-HH-mm}-%i.log">
            <!--日誌級別過濾器-->
            <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY" />
            <!--日誌消息格式-->
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %msg%n" />
            <Policies>
                <!--在系統啓動時,出發拆分規則,生產一個新的日誌文件-->
                <OnStartupTriggeringPolicy />
                <!--按照文件大小拆分,10MB -->
                <SizeBasedTriggeringPolicy size="10 MB" />
                <!--按照時間節點拆分,規則根據filePattern定義的-->
                <TimeBasedTriggeringPolicy />
            </Policies>
            <!--在同一個目錄下,文件的個數限定爲 30 個,超過進行覆蓋-->
            <DefaultRolloverStrategy max="30" />
        </RollingFile>

    </Appenders>

    <!--logger 定義-->
    <Loggers>


        <!--自定義異步 logger 對象
            includeLocation="false" 關閉日誌記錄的行號信息
            additivity="false" 不在繼承 rootlogger 對象
        -->
        <AsyncLogger name="com.leon" level="trace" includeLocation="false" additivity="false">
            <AppenderRef ref="Console"/>
        </AsyncLogger>


        <!--使用 rootLogger 配置 日誌級別 level="trace"-->
        <Root level="trace">
            <!--指定日誌使用的處理器-->
            <AppenderRef ref="Console" />

            <!--使用異步 appender-->
            <AppenderRef ref="Async" />
        </Root>
    </Loggers>
</Configuration>

記錄峯值吞吐量

下圖比較了同步記錄器,異步附加器和異步記錄器的吞吐量。這是所有線程在一起的總吞吐量。在具有64個線程的測試中,異步記錄器比異步附加器快12倍,比同步記錄器快68倍。

異步記錄器的吞吐量隨線程數的增加而增加,而同步記錄器和異步附加程序都具有或多或少的恆定吞吐量,而與執行記錄的線程數無關。

與其他日誌記錄包的異步吞吐量比較

我們還將異步記錄器的峯值吞吐量與其他日誌記錄包(尤其是log4j-1.2.17和logback-1.0.10)中可用的同步記錄器和異步附加程序進行了比較,結果相似。對於異步附加程序,添加更多線程時,所有線程的總日誌記錄吞吐量大致保持不變。在多線程方案中,異步記錄器可以更有效地利用計算機上可用的多個內核。

Log4j2的性能

Log4j2最牛的地方在於異步輸出日誌時的性能表現,Log4j2在多線程的環境下吞吐量與Log4j和Logback的比較如下圖。下圖比較中Log4j2有三種模式:

1)全局使用異步模式;

2)部分Logger採用異步模式;

3)異步Appender。可以看出在前兩種模式下,Log4j2的性能較之Log4j和Logback有很大的優勢。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章