我在Multi-threaded java
实例中运行了google compute engine
个应用程序,此应用程序最多可以达到1万个线程,每个执行任务的人可能会达到30分钟的执行时间。
除了问题之外,一切顺利,我需要在运行这些5k线程的任务中记录一些信息,所以每当我在这些任务中放入一些日志甚至1个日志时,它会导致性能下降导致许多线程尝试登录同时 - 被认为是一个IO操作 - 所以大多数时候它们中的大多数都会被阻塞
我开始使用谷歌搜索,我找到了一些解决方案:
1- log4j
及其AsynchronousLogger
功能使用disruptor
和RandomAccessFile
,其惊人且超级快速(所有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);
}
}
提前致谢