2016-03-28 5 views
1

1. In meiner Anwendung, die Daten über TCP-Verbindung (Kafka Producer) sendet, beobachtete ich drastische Leistungsabfall, wenn die Größe der Nachricht wird größer von 1 MB bis 100 MB. (140 MB/s -> 25 MB/s) (Stapelgröße = 1)Producer (Java-Client) hat Leistungsabfälle, wenn die Nachrichtengröße ist sehr groß (wie ~ 100mb)

Ich profilierte den Erzeugerprozess und fand einen verdächtigen Punkt: Eine Methode 'copyFromArray' in Bits.java verbraucht die meiste Zeit. (Die Codes sind wie folgt.)

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; 
    } 
} 

Referenz: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/nio/Bits.java

2. Interessanter dieses Problem tritt nur auf, wenn ich den Hersteller-Client (Java-Implementierung) verwenden, aber tritt nicht auf, wenn ich die man verwenden (Scala-Implementierung), die ich nicht verstehen kann.

Wo soll ich anfangen zu finden, was das Problem hier ist?

+0

'mb' = Milli-Bits,' MB' = Mega-Bytes. Es ist nicht ungewöhnlich, die meiste Zeit damit zu verbringen, Daten zu kopieren, wenn Sie sehr große Nachrichten haben. Ich hätte gedacht, dass Scala den gleichen Code wie der Java-Client aufruft. –

+0

@PeterLawrey (Ich habe mb -> MB repariert, vielen Dank dafür.) Der Scala-Client ruft genau die gleiche Methode auf wie der Java-Client gemäß den Profilergebnissen. – syko

+0

Sie haben also recht, dass es genau so funktionieren sollte, da es den gleichen Code ausführt. –

Antwort

1

Kafkas optimale Nachrichtengröße liegt bei 1k. Wenn Ihre Nachrichtengröße größer als 10M ist, beginnt das Leistungsproblem. In Ihrem Fall beträgt die Nachrichtengröße ungefähr 100 MB. Das ist definitiv ein Nein, nein.

Sie müssen sich fragen, ob das Senden einer so großen Nachricht notwendig ist. Kafka ist ein Event-Pub-Sub-System, kein FTP-Server. Wenn Sie eine große Datei senden müssen, können Sie die Datei an einem freigegebenen Speicherort ablegen und die URL als Nachricht über Kafka senden. Wenn dies nicht funktioniert, können Sie Ihren Producer so programmieren, dass große Nachrichten mit demselben Schlüssel in mehrere Teile aufgeteilt werden. Auf diese Weise garantieren Sie, dass die Nachrichten mit demselben Schlüssel auf derselben Partition landen. Sie können die Nachrichten auf der Verbraucherseite zusammenstellen. Wenn Sie die Komprimierung verwenden, wird die Größe Ihrer Nachricht verringert, um die Leistung zu verbessern.

Kurz gesagt, sollten Sie vermeiden, große Nachrichten (> 10M) über Kafka zu senden.

+0

Ich bin sicher, dass Kafka nicht zum Übertragen von großen Nachrichten dient. Ich gebe Kafka dafür keine Schuld. Ich möchte nur wissen, warum Scala und Java-Code sich anders verhalten. Sie können sich fragen, ob dieses Problem irgendeine Beziehung zu Apache Kafkas Architektur hat, mit der ich nicht völlig einverstanden bin. – syko

+0

@syko Leider habe ich den Zweck Ihrer Frage nicht verstanden. Soweit ich weiß, ist die Scala-Hersteller-Implementierung die alte API und der Java-Produzent ist die neue.Ich habe keine Erklärung, warum sie anders funktionieren, weil der Grund alles sein könnte - Bugs, Konfigurationsstandardänderungen zwischen Releases, eigener Code, etc. Die Aussage, dass "Kafka große Nachrichten vermeiden sollte", bleibt wahr. – Lan