1

我有一个Multi-threaded java在实例中运行的应用程序google compute engine,这个应用程序可能会达到 10k 线程,每个执行任务的线程可能会达到 30 分钟的执行时间。

一切顺利,除了只有问题,我需要在那些 5k 线程正在运行的任务中记录一些信息,所以每当我在这些任务中放置一些日志甚至 1 个日志时,它都会降低性能,因为许多线程试图同时记录 - 考虑成为一个 IO 操作 - 所以它们中的大多数大部分时间都会被 BLOCKED

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

1-log4j它的AsynchronousLogger功能使用disruptorand RandomAccessFile,它的速度惊人且超快(所有 CPU 内核都 97% 忙),但它会将日志写入文件 - 可能很容易达到 100Gb - 所以我不推荐这个。
(我希望我能找到一种方法让 log4jGoogle StackDriver以相同的性能直接写入)

2-我试过使用ConcurrentLinkedQueue,所以所有线程都会将日志推送到这个队列,并且有线程从这个队列轮询日志并将它们发布到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);
          }

      }

提前致谢

4

0 回答 0