如何处理multiThread java应用程序中的日志记录?

时间:2018-02-13 10:35:54

标签: multithreading logging google-compute-engine disruptor-pattern google-cloud-stackdriver

我在Multi-threaded java实例中运行了google compute engine个应用程序,此应用程序最多可以达到1万个线程,每个执行任务的人可能会达到30分钟的执行时间。

除了问题之外,一切顺利,我需要在运行这些5k线程的任务中记录一些信息,所以每当我在这些任务中放入一些日志甚至1个日志时,它会导致性能下降导致许多线程尝试登录同时 - 被认为是一个IO操作 - 所以大多数时候它们中的大多数都会被阻塞

我开始使用谷歌搜索,我找到了一些解决方案:

1- log4j及其AsynchronousLogger功能使用disruptorRandomAccessFile,其惊人且超级快速(所有CPU内核占97%)但它写道登录到文件 - 可能很容易达到100Gb - 所以我不推荐这个 (我希望我能找到一种方法让log4j直接以相同的性能写入Google StackDriver

2-我尝试使用ConcurrentLinkedQueue,因此所有线程都会将日志推送到此队列,并且有来自此队列的Thread(s)轮询日志并将其发布到google StackDriver。性能降低到log4j性能的1/10。

3-我已经读过关于Disruptor并且我已经开始使用它,而且性能非常糟糕,最糟糕的结果是大多数线程都在等待寻找一个免费插槽,我将与您分享我的代码可能是我做错了什么:

public class CloudLogger {

        private  static Disruptor<LogEntryEvent> disruptor;
        private static RingBuffer<LogEntryEvent> ringBuffer;
        private static final int RING_BUFFER_SIZE = 1024 * 1024;    

    static {
        disruptor = new Disruptor<LogEntryEvent>(LogEntryEvent.FACTORY , RING_BUFFER_SIZE, new ThreadFactoryLogImpl(), ProducerType.MULTI, new SleepingWaitStrategy());
        disruptor.handleEventsWith(new LogEntryHandler());
        disruptor.start();
        ringBuffer = disruptor.getRingBuffer();
        }

    private static void log(LogEntry logEntry) {
         long sequence = ringBuffer.next();
           final LogEntryEvent _logEntry = ringBuffer.get(sequence);
            _logEntry.setLogEntry(logEntry);
            ringBuffer.publish(sequence);
        }
}

LogEntryEvent.class

 public class LogEntryEvent 
        {

             public LogEntryEvent() {
                    // do nothing
            }

            LogEntry logEntry;

            public static final EventFactory<LogEntryEvent> FACTORY = new EventFactory<LogEntryEvent>()
            {
                public LogEntryEvent newInstance()
                {
                    return new LogEntryEvent();
                }
            };

            public LogEntry getLogEntry() {
                return logEntry;
            }

            public void setLogEntry(LogEntry logEntry) {
                this.logEntry = logEntry;
            }

        }

ThreadFActoryLogImpl.class

public class ThreadFactoryLogImpl implements ThreadFactory {

            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setPriority(Thread.MAX_PRIORITY);
                t.setName("Writting logs thread");
                return t;
            }
        }

LogEntryHandler.class

public class LogEntryHandler implements EventHandler<LogEntryEvent>
      {
          public void onEvent(final LogEntryEvent logEntry, final long sequence, final boolean endOfBatch) throws Exception
          {
            // I should post here to cloud StackDriver, but Im just testing the performance without it  
              System.out.println(" got sequance is " + sequence + " end of natch " + endOfBatch);
          }

      }

提前致谢

0 个答案:

没有答案