我有一个Multi-threaded java
在实例中运行的应用程序google compute engine
,这个应用程序可能会达到 10k 线程,每个执行任务的线程可能会达到 30 分钟的执行时间。
一切顺利,除了只有问题,我需要在那些 5k 线程正在运行的任务中记录一些信息,所以每当我在这些任务中放置一些日志甚至 1 个日志时,它都会降低性能,因为许多线程试图同时记录 - 考虑成为一个 IO 操作 - 所以它们中的大多数大部分时间都会被 BLOCKED
我已经开始用谷歌搜索,我找到了一些解决方案:
1-log4j
它的AsynchronousLogger
功能使用disruptor
and 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);
}
}
提前致谢