当消息大小非常大(如~100mb)时,Producer(java客户端)的性能会下降

当消息大小非常大(如~100mb)时,Producer(java客户端)的性能会下降,java,scala,apache-kafka,Java,Scala,Apache Kafka,1。在通过TCP连接发送数据的应用程序(Kafka Producer)中,我发现当消息大小从1MB增大到100MB时,性能会急剧下降。(140 MB/秒-->25 MB/秒)(批量大小=1) 我分析了producer进程,发现了一个可疑点:Bits.java中的方法“copyFromArray”占用了大部分时间。(代码如下所示。) 参考: 2.有趣的是,这个问题只在我使用producer客户端(java实现)时出现,而在我使用我无法理解的producer客户端(scala实现)时不会出现 我应该

1。在通过TCP连接发送数据的应用程序(Kafka Producer)中,我发现当消息大小从1MB增大到100MB时,性能会急剧下降。(140 MB/秒-->25 MB/秒)(批量大小=1)

我分析了producer进程,发现了一个可疑点:Bits.java中的方法“copyFromArray”占用了大部分时间。(代码如下所示。)

参考:

2.有趣的是,这个问题只在我使用producer客户端(java实现)时出现,而在我使用我无法理解的producer客户端(scala实现)时不会出现


我应该从哪里开始查找问题所在?

卡夫卡的最佳消息大小约为1k。如果您的消息大小大于10M,则会出现性能问题。在您的情况下,消息大小约为100MB。那绝对是不可以的

你必须扪心自问,是否有必要发出如此重大的信息。Kafka是一个事件发布子系统,而不是FTP服务器。如果需要发送大文件,可以将文件放在共享位置,然后通过Kafka将url作为消息发送。如果这不起作用,另一个解决方法是对制作人进行编码,以使用相同的密钥将大型消息分成多个部分。通过这种方式,您可以保证具有相同密钥的消息将在同一分区上结束。您可以在消费者端重新组合消息。此外,使用压缩将减少消息的大小以提高性能


简而言之,您应该避免通过卡夫卡发送大型消息(>10M)

mb
=毫位,
mb
=兆字节。如果您有非常大的消息,那么花费大部分时间复制数据并不罕见。我本以为Scala调用的代码与Java客户端的代码相同。@PeterLawrey(我修复了mb-->mb,谢谢)。Scala客户端根据分析结果调用的方法与Java客户端完全相同。因此,您是对的,它应该以完全相同的方式执行,因为它正在运行相同的代码。如果您只是在同一类型的两个数组之间复制,那么在不安全的\u copy\u THRESHOLD块中复制不是更快吗?问题可能是消息大小本身。TCP数据包的大小显然因各种因素而不同,为了安全地发送数据,您的制作人可能需要花费大量时间将您的消息分解为许多较小的数据包。我确信卡夫卡不适合传输大容量信息。我并没有为此责备卡夫卡。我只是想知道为什么scala和java代码的行为不同。您可以问问自己,这个问题是否与Apache Kafka的体系结构有任何关系,我并不完全同意。@syko抱歉,我不理解您问题的目的。据我所知,scala producer实现是旧API,Java producer是新API。我无法解释它们为何表现不同,因为原因可能是任何东西——bug、版本之间的配置默认更改、您自己的代码等等。“卡夫卡应该避免大尺寸消息”的说法仍然正确。
static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L;

static void copyFromArray(Object src, long srcBaseOffset, long srcPos,
                          long dstAddr, long length)
{
    long offset = srcBaseOffset + srcPos;
    while (length > 0) {
        long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
        unsafe.copyMemory(src, offset, null, dstAddr, size);
        length -= size;
        offset += size;
        dstAddr += size;
    }
}