the*_*chy 4 java apache-kafka log4j2
我在使用 log4j2 (2.5) 和 Kafka (0.10.1.0) 时遇到了性能问题。当我在 log4j2.xml 文件中启用 Kafka 时,我的应用程序会变慢到爬行,同时只向 Kafka 代理输出大约 200KB/s 的事件。这比 Kafka 应该实现的目标低几个数量级(https://engineering.linkedin.com/kafka/benchmarking-apache-kafka-2-million-writes-second-three-cheap-machines)。
这是我的 log4j2.xml 配置文件的相关部分:
<Kafka name="KafkaAll" topic="all">
<PatternLayout pattern="%date %message" />
<Property name="bootstrap.servers">localhost:9092</Property>
<Property name="buffer.memory">67108864</Property>
<Property name="batch.size">8196</Property>
<Property name="acks">1</Property>
</Kafka>
Run Code Online (Sandbox Code Playgroud)
在运行一些测试之后,我已经能够确定问题并发现 Kafka 附带的 ProducerPerformance 测试确实实现了不错的性能。它的性能约为 5MB/s,具有类似大小的 100 字节消息。经过大量测试,我发现不同之处不在于配置,而在于实现调用的方式。log4j2 KafkaAppender 使用 KafkaManager 类将日志写入 Kafka:
public void send(final byte[] msg) throws ExecutionException, InterruptedException, TimeoutException {
if (producer != null) {
producer.send(new ProducerRecord<byte[], byte[]>(topic, msg)).get(timeoutMillis, TimeUnit.MILLISECONDS);
}
}
Run Code Online (Sandbox Code Playgroud)
性能问题是由调用“get”方法引起的,该方法会阻塞直到发送完成。有趣的是,Kafka 中包含一个 log4j appender,它确实考虑到了这个问题:
Future<RecordMetadata> response = producer.send(new ProducerRecord<byte[], byte[]>(topic, message.getBytes()));
if (syncSend) {
try {
response.get();
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
} catch (ExecutionException ex) {
throw new RuntimeException(ex);
}
}
Run Code Online (Sandbox Code Playgroud)
换句话说,当 syncSend 设置为 false 时,对 send 的调用会立即返回。然而,在 KafkaAppender 的 log4j2 实现中找不到这个“syncSend”属性。
我尝试通过其他方式使调用异步,例如使用 log4j2 附带的 AsyncAppender 并将 acks 属性设置为 0 而不是 1。但是,没有任何设置通过不等待发送完成来实现性能提升。我也尝试使用 Kafka 附带的 log4j appender,但我没有设法让它与 log4j2 一起工作(我想坚持使用 log4j2)。
所以,最后,我决定分叉 log4j2 附带的 KafkaAppender 并删除调用的阻塞部分。这有效,但当然我更愿意使用现成的软件包。
有没有人也遇到过这个问题?你是如何解决这个问题的?有没有更简单的方法而不改变代码?
| 归档时间: |
|
| 查看次数: |
1534 次 |
| 最近记录: |