Asynchronous 异步模式下的Log4j2在重负载下仍会阻塞java.util.concurrent.lock

Asynchronous 异步模式下的Log4j2在重负载下仍会阻塞java.util.concurrent.lock,asynchronous,log4j2,Asynchronous,Log4j2,我正在尝试在低延迟环境中登录。 2个高优先级线程正在紧密循环中调用log.error()(1Mmessages/s) 我想使用异步日志记录(使用中断器)并丢弃任何多余的消息。因此,调用线程永远不会阻塞 然而,jstack清楚地显示它大约每秒阻塞100次 是我的配置不对吗? 或者,如果缓冲区填满,阻塞是否不可避免 java -Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector -Dl

我正在尝试在低延迟环境中登录。
2个高优先级线程正在紧密循环中调用log.error()(1Mmessages/s)

我想使用异步日志记录(使用中断器)并丢弃任何多余的消息。因此,调用线程永远不会阻塞

然而,jstack清楚地显示它大约每秒阻塞100次

是我的配置不对吗? 或者,如果缓冲区填满,阻塞是否不可避免

java -Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
-Dlog4j2.AsyncQueueFullPolicy=Discard
-Dlog4j2.DiscardThreshold=Trace
-DAsyncLogger.RingBufferSize=2000000 TestLog


"TT0" #14 prio=5 os_prio=0 tid=0x00007fe8cc690800 nid=0x2463 runnable [0x00007fe8ae70d000]
   java.lang.Thread.State: RUNNABLE
        at sun.misc.Unsafe.unpark(Native Method)
        at java.util.concurrent.locks.LockSupport.unpark(LockSupport.java:141)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.unparkSuccessor(AbstractQueuedSynchronizer.java:662)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1264)
        at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
        at com.lmax.disruptor.BlockingWaitStrategy.signalAllWhenBlocking(BlockingWaitStrategy.java:72)
        at com.lmax.disruptor.MultiProducerSequencer.publish(MultiProducerSequencer.java:218)
        at com.lmax.disruptor.RingBuffer.translateAndPublish(RingBuffer.java:934)
        at com.lmax.disruptor.RingBuffer.publishEvent(RingBuffer.java:444)
        at com.lmax.disruptor.dsl.Disruptor.publishEvent(Disruptor.java:245)
        at org.apache.logging.log4j.core.async.AsyncLogger.logMessage(AsyncLogger.java:285)
        at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:727)
        at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:716)
        at org.apache.logging.log4j.spi.AbstractLogger.debug(AbstractLogger.java:232)
        at TestLog$WriteToFile.run(TestLog.java:53)
        at java.lang.Thread.run(Thread.java:745)

"AsyncLogger-1" #12 daemon prio=5 os_prio=0 tid=0x00007fe8cc96f800 nid=0x2460 waiting on condition [0x00007fe8b4187000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000007104a0f28> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
        at com.lmax.disruptor.BlockingWaitStrategy.waitFor(BlockingWaitStrategy.java:45)
        at com.lmax.disruptor.ProcessingSequenceBarrier.waitFor(ProcessingSequenceBarrier.java:55)
        at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:123)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
java-Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
-Dlog4j2.AsyncQueueFullPolicy=Discard
-Dlog4j2.DiscardThreshold=跟踪
-DAsyncLogger.RingBufferSize=2000000测试日志
“TT0”#14优先级=5操作系统优先级=0 tid=0x00007fe8cc690800 nid=0x2463可运行[0x00007fe8ae70d000]
java.lang.Thread.State:可运行
在sun.misc.Unsafe.unpark(本机方法)
位于java.util.concurrent.locks.LockSupport.unpark(LockSupport.java:141)
位于java.util.concurrent.locks.AbstractQueuedSynchronizer.unparkSuccessor(AbstractQueuedSynchronizer.java:662)
位于java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1264)
位于java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
BlockingWaitStrategy.signallwhenblocking(BlockingWaitStrategy.java:72)
在com.lmax.disruptor.MultiProducerSequencer.publish(MultiProducerSequencer.java:218)上
位于com.lmax.disruptor.RingBuffer.translateAndPublish(RingBuffer.java:934)
位于com.lmax.disruptor.RingBuffer.publishEvent(RingBuffer.java:444)
位于com.lmax.disruptor.dsl.disruptor.publishEvent(disruptor.java:245)
位于org.apache.logging.log4j.core.async.AsyncLogger.logMessage(AsyncLogger.java:285)
位于org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:727)
位于org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:716)
位于org.apache.logging.log4j.spi.AbstractLogger.debug(AbstractLogger.java:232)
在TestLog$WriteToFile.run处(TestLog.java:53)
运行(Thread.java:745)
“AsyncLogger-1”#12守护进程优先级=5 os_优先级=0 tid=0x00007fe8cc96f800 nid=0x2460等待条件[0x00007FE8B418700]
java.lang.Thread.State:等待(停车)
在sun.misc.Unsafe.park(本机方法)
-停车等待(java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
位于java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
位于java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
位于com.lmax.disruptor.BlockingWaitStrategy.waitFor(BlockingWaitStrategy.java:45)
位于com.lmax.disruptor.ProcessingSequenceBarrier.waitFor(ProcessingSequenceBarrier.java:55)
位于com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:123)
位于java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
位于java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
运行(Thread.java:745)

LMAX Disruptor允许您选择后台线程在等待工作到达时应该做什么

默认情况下,Log4j2使用BlockingWaitStrategy。这提供了您所看到的行为,这适用于大多数情况,但可能不适用于超低延迟用例

如果可以将一个内核专用于后台线程,则可以使用BusySpin等待策略


请参见

我正在显示1 writer的堆栈跟踪和log4j2线程我关心的是作为主应用程序线程的“TT0”。它似乎正在接受一个同步数据结构,这让我感到惊讶。如果每次我做一个jstack我都会看到它,那么我猜它在那里花费了很多时间。是的,如果你使用忙碌等待策略,这也会消失。目前,应用程序线程需要使用锁来通知后台线程,它应该被唤醒,因为工作已经完成。太好了。这是有道理的。