2016-03-28 23 views
1

1.在我通過TCP連接(Kafka Producer)發送數據的應用程序中,當消息大小從1MB變大到100MB。 (140 MB /秒 - > 25 MB /秒)(批量大小= 1)生產者(java客戶端)在消息大小非常大時(如〜100mb)性能下降

我對生產者進程進行了概要分析,發現一個可疑點:Bits.java中的方法'copyFromArray'消耗大部分時間。 (該代碼如下。)

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

參考:當我使用生產者客戶端(Java實現)http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/nio/Bits.java

2.有趣的是隻出現此問題,但是當我使用一個不會發生(scala實現),我不明白。

我應該從哪裏開始找到問題所在?

+0

'mb' =毫比特,'MB' =兆字節。如果你有很大的消息,花費大部分時間複製數據並不罕見。我會認爲Scala調用與Java客戶端相同的代碼。 –

+0

@PeterLawrey(我修復了MB - > MB,非常感謝。)根據分析結果,Scala客戶端調用與Java客戶端完全相同的方法。 – syko

+0

所以你是對的,它應該以完全相同的方式執行,因爲它運行的是相同的代碼。 –

回答

1

卡夫卡的最佳消息大小約爲1k。如果您的郵件大小超過10M,則會出現性能問題。就你而言,消息大小約爲100MB。這絕對是一個不錯的選擇。

你必須問自己是否需要發送這樣的大消息。 Kafka是一個事件發佈系統,而不是FTP服務器。如果你需要發送大文件,你可以把文件放在一個共享位置,然後通過Kafka發送url作爲消息。如果這不起作用,另一個解決方法是編寫您的生產者用相同的密鑰將大消息分成多個部分。這樣你可以保證具有相同密鑰的消息最終在同一個分區上。您可以將消息組裝回客戶端。同樣使用壓縮將減少消息的大小以提高性能。

總之,你應該避免通過卡夫卡發送大量消息(> 10M)。

+0

我相信Kafka不會傳輸大型郵件。我不是在爲這個卡夫卡指責。我只想知道爲什麼scala和java代碼的行爲有所不同。 您可以問問自己,這個問題與Apache Kafka的架構是否有任何關係,我並不完全同意。 – syko

+0

@syko對不起,我不明白你的問題的目的。據我所知,scala生產者實現是舊的API,而Java生產者是新的。我沒有解釋爲什麼它們的表現不同,原因可能是什麼 - 錯誤,發佈之間的配置默認更改,您自己的代碼等。「Kafka應避免大尺寸消息」的聲明保持爲真。 – Lan