用asyncRoot
配置对应的对接disruptor类是AsyncLoggerConfigDisruptor
,用Log4jContextSelector
启动参数配置全局异步的对应的对接disruptor类是AsyncLoggerDisruptor
。下面分析的是AsyncLoggerConfigDisruptor
html
AsyncLoggerConfigDisruptor.start
方法用来建立并启动disruptor
实例
建立disruptor须要EventFactory
,ringBuffer的大小
,ThreadFactory
,ProducerType
,等待策略waitStrategy
建立后须要设置ExceptionHandler
,设置EventHandler
。
发布(生产)事件的translator。java
分是否可变(mutable
字段)场景对应两个不一样的EventFactory。
不可变的factory的逻辑是:apache
@Override public Log4jEventWrapper newInstance() { return new Log4jEventWrapper(); }
可变的factory逻辑是:app
public Log4jEventWrapper newInstance() { return new Log4jEventWrapper(new MutableLogEvent()); }
会在 Log4jEventWrapper
的构造函数中传入MutableLogEvent
实例。异步
是根据AsyncLoggerConfig.RingBufferSize
配置值算出来的。
这个配置项的值最小不能小于128,默认值分两种状况进行设定:若是启用了ENABLE_THREADLOCALS(优化GC的一个配置项),那么默认值是4 * 1024
,不然是256 * 1024
。
这个配置是经过System properties指定,一样存在不一样版本,配置项名称不一致的状况,log4j2.asyncLoggerRingBufferSize (AsyncLogger.RingBufferSize)。详细能够参见这里async
主要是定制线程名:
线程名格式是:"AsyncLoggerConfig-" + FACTORY_NUMBER(自增) + "-" + threadFactoryName + "-" + THREAD_NUMBER(自增)
默认的实际示例是: Log4j2-TF-1-AsyncLoggerConfig--1,跟上面的有些差别,上面的分析错了吗??ide
多生产者函数
默认是10ms的TimeoutBlockingWaitStrategy。 支持可配置SleepingWaitStrategy
、YieldingWaitStrategy
、BlockingWaitStrategy
、BusySpinWaitStrategy
、TimeoutBlockingWaitStrategy
。
这个配置是经过System properties指定,一样存在不一样版本,配置项名称不一致的状况,log4j2.asyncLoggerWaitStrategy (AsyncLogger.WaitStrategy)。优化
能够配置,配置项名称是AsyncLoggerConfig.ExceptionHandler,默认是用AsyncLoggerConfigDefaultExceptionHandler,打印: AsyncLogger error handling event seq=..., value=...,并打出异常栈。ui
此处使用了 Log4jEventWrapperHandler RingBufferLogEventHandler,是disruptor的SequenceReportingEventHandler实现。
/** * EventHandler performs the work in a separate thread. */ private static class Log4jEventWrapperHandler implements SequenceReportingEventHandler<Log4jEventWrapper> { private static final int NOTIFY_PROGRESS_THRESHOLD = 50; private Sequence sequenceCallback; private int counter; @Override public void setSequenceCallback(final Sequence sequenceCallback) { this.sequenceCallback = sequenceCallback; } @Override public void onEvent(final Log4jEventWrapper event, final long sequence, final boolean endOfBatch) throws Exception { event.event.setEndOfBatch(endOfBatch); event.loggerConfig.asyncCallAppenders(event.event); event.clear(); notifyIntermediateProgress(sequence); } /** * Notify the BatchEventProcessor that the sequence has progressed. Without this callback the sequence would not * be progressed until the batch has completely finished. */ private void notifyIntermediateProgress(final long sequence) { if (++counter > NOTIFY_PROGRESS_THRESHOLD) { sequenceCallback.set(sequence); counter = 0; } } }
event.loggerConfig.asyncCallAppenders(event.event); 这个会触发日志的输出
跟EventFactory
同样分mutable
是否可变的两种状况。
不可变:
private static final EventTranslatorTwoArg<Log4jEventWrapper, LogEvent, AsyncLoggerConfig> TRANSLATOR = new EventTranslatorTwoArg<Log4jEventWrapper, LogEvent, AsyncLoggerConfig>() { @Override public void translateTo(final Log4jEventWrapper ringBufferElement, final long sequence, final LogEvent logEvent, final AsyncLoggerConfig loggerConfig) { ringBufferElement.event = logEvent; ringBufferElement.loggerConfig = loggerConfig; } };
可变:
/** * Object responsible for passing on data to a RingBuffer event with a MutableLogEvent. */ private static final EventTranslatorTwoArg<Log4jEventWrapper, LogEvent, AsyncLoggerConfig> MUTABLE_TRANSLATOR = new EventTranslatorTwoArg<Log4jEventWrapper, LogEvent, AsyncLoggerConfig>() { @Override public void translateTo(final Log4jEventWrapper ringBufferElement, final long sequence, final LogEvent logEvent, final AsyncLoggerConfig loggerConfig) { ((MutableLogEvent) ringBufferElement.event).initFrom(logEvent); ringBufferElement.loggerConfig = loggerConfig; } };
都是完成一个事情给ringBufferElement元素的event赋值或者初始化。
先看按下调用栈:
Daemon Thread [Log4j2-TF-1-AsyncLoggerConfig--1] (Suspended (breakpoint at line 37 in PatternFormatter)) PatternFormatter.format(LogEvent, StringBuilder) line: 37 PatternLayout$PatternSerializer.toSerializable(LogEvent, StringBuilder) line: 334 PatternLayout.toText(AbstractStringLayout$Serializer2, LogEvent, StringBuilder) line: 233 PatternLayout.encode(LogEvent, ByteBufferDestination) line: 218 PatternLayout.encode(Object, ByteBufferDestination) line: 58 ConsoleAppender(AbstractOutputStreamAppender<M>).directEncodeEvent(LogEvent) line: 177 ConsoleAppender(AbstractOutputStreamAppender<M>).tryAppend(LogEvent) line: 170 ConsoleAppender(AbstractOutputStreamAppender<M>).append(LogEvent) line: 161 AppenderControl.tryCallAppender(LogEvent) line: 156 AppenderControl.callAppender0(LogEvent) line: 129 AppenderControl.callAppenderPreventRecursion(LogEvent) line: 120 AppenderControl.callAppender(LogEvent) line: 84 AsyncLoggerConfig(LoggerConfig).callAppenders(LogEvent) line: 448 AsyncLoggerConfig.asyncCallAppenders(LogEvent) line: 129 AsyncLoggerConfigDisruptor$Log4jEventWrapperHandler.onEvent(AsyncLoggerConfigDisruptor$Log4jEventWrapper, long, boolean) line: 111 AsyncLoggerConfigDisruptor$Log4jEventWrapperHandler.onEvent(Object, long, boolean) line: 97 BatchEventProcessor<T>.run() line: 129 Log4jThread(Thread).run() line: 748
Log4jEventWrapperHandler.onEvent 111行是event.loggerConfig.asyncCallAppenders(event.event),参见上面EventHandler,此处完成日志真正写出。