本篇文章介紹Kafka處理大檔案出現記憶體溢位 java.lang.OutOfMemoryError: Direct buffer memory,主要內容包括基礎應用、實用技巧、原理機制等方面,希望對大家有所幫助。
kafka是由scala和java編寫的。因此須要調一些jvm的引數。java的記憶體分為堆內記憶體和堆外記憶體。
-Xms2048m, -Xmx2048m,設定的是堆內記憶體。
-Xms是初始可用的最大堆內記憶體。-Xmx設定的是最大可用的堆內記憶體。兩者設定成同樣是由於效率問題,可讓jvm少作一些運算。若是這兩個引數設定的過小,kafka會出現java.lang.OutOfMemoryError: Java heap space的錯誤。
-XX:MaxDirectMemorySize=8192m。這個引數設定的過小,kafka會出現java.lang.OutOfMemoryError: Direct buffer memory的錯誤。 由於kafka的網路IO使用了java的nio中的DirectMemory的方式,而這個申請的是堆外記憶體。
Kafka設計的初衷是迅速處理短小的訊息,一般10K大小的訊息吞吐效能最好。但有時候,我們需要處理更大的訊息,比如XML檔案或JSON內容,一個訊息差不多有10-100M,這種情況下,Kakfa應該如何處理?
不過如果上述方法都不是你需要的,而你最終還是希望傳送大的訊息,那麼,則可以在kafka中設定下面一些引數:
注意:message.max.bytes,要設定大於傳送最巨量資料的大小,不然會produce失敗。
broker為什麼會返回總量為1000大小的資料呢?
librdkafka有這樣一個引數:fetch.max.bytes, 它有這樣的描述:
Maximum amount of data the broker shall return for a Fetch request. Messages are fetched in batches by the consumer and if the first message batch in the first non-empty partition of the Fetch request is larger than this value, then the message batch will still be returned to ensure the consumer can make progress. The maximum message batch size accepted by the broker is defined via message.max.bytes (broker config) or max.message.bytes (broker topic config). fetch.max.bytes is automatically adjusted upwards to be at least message.max.bytes (consumer config).
receive.message.max.bytes(預設 1MB) : kafka協定response的最大長度,也是消費者能讀取的最大訊息。這個值應該大於或等於message.max.bytes,不然消費會失敗。
receive.message.max.bytes
只支援1000到1000000000。否則會出現 「Receive failed: Invalid message size 1047207987 (0..1000000000): increase receive.message.max.bytes」這樣的錯誤。
注意:一定要選擇kafka來傳送大的訊息,還有些事項需要考慮。要傳送大的訊息,不是當出現問題之後再來考慮如何解決,而是在一開始設計的時候,就要考慮到大訊息對叢集和主題的影響。
Brokers會為每個分割區分配replica.fetch.max.bytes引數指定的記憶體空間,假設replica.fetch.max.bytes=1M,且有1000個分割區,則需要差不多1G的記憶體,確保分割區數 * 最大的訊息不會超過伺服器的記憶體,否則會報OOM錯誤。
消費端的fetch.message.max.bytes指定了最大訊息需要的記憶體空間,同樣,分割區數 * 最大需要記憶體空間不能超過伺服器的記憶體。所以,如果你有大的訊息要傳送,則在記憶體一定的情況下,只能使用較少的分割區數或者使用更大記憶體的伺服器。
到現在為止,我在kafka的使用中還沒發現過此問題,但這應該是一個需要考慮的潛在問題。更大的訊息會讓GC的時間更長(因為broker需要分配更大的塊),隨時關注GC的紀錄檔和伺服器的紀錄檔資訊。如果長時間的GC導致kafka丟失了zookeeper的對談,則需要設定zookeeper.session.timeout.ms引數為更大的超時時間。
G1>CMS的優勢
G1適合的場景:
KAFKA_JVM_PERFORMANCE_OPTS="-server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+DisableExplicitGC -Djava.awt.headless=true"
所以只需要修改kafka-server-start.sh。這裡面將記憶體設定為4G,因為當前kafka的堆記憶體使用了800多M,1個G的記憶體不夠用。但是分配太多,也沒什麼用,還容易影響到pagecache,降低效率:
export KAFKA_HEAP_OPTS="-Xms4g -Xmx4g"
Brokers allocate a buffer the size of replica.fetch.max.bytes for each partition they replicate. If replica.fetch.max.bytes is set to 1 MiB, and you have 1000 partitions, about 1 GiB of RAM is required. Ensure that the number of partitions multiplied by the size of the largest message does not exceed available memory.
The same consideration applies for the consumer fetch.message.max.bytes setting. Ensure that you have enough memory for the largest message for each partition the consumer replicates. With larger messages, you might need to use fewer partitions or provide more RAM.
若是一個訊息須要的處理時間很長,broker會認為consumer已經掛了,把partition分配給其餘的consumer,而後迴圈往復, 這條record永遠無法消費。方法是增長max.poll.interval.ms 引數。
Don't fear the filesystem!中提到kafka使用page cache進行檔案儲存。計算機的記憶體分為虛擬記憶體和實體記憶體。實體記憶體是真實的記憶體,虛擬記憶體是用磁碟來代替記憶體。並通過swap機制實現磁碟到實體記憶體的載入和替換,這裡面用到的磁碟我們稱為swap磁碟。
在寫檔案的時候,Linux首先將資料寫入沒有被使用的記憶體中,這些記憶體被叫做記憶體頁(page cache)。然後讀的時候,Linux會優先從page cache中查詢,如果找不到就會從硬碟中查詢。
當實體記憶體使用達到一定的比例後,Linux就會使用進行swap,使用磁碟作為虛擬記憶體。通過cat /proc/sys/vm/swappiness可以看到swap引數。這個參數列示虛擬記憶體中swap磁碟佔了多少百分比。0表示最大限度的使用記憶體,100表示儘量使用swap磁碟。
系統預設的引數是60,當實體記憶體使用率達到40%,就會頻繁進行swap,影響系統效能,推薦將vm.swappiness 設定為較低的值1。最終我設定為10,因為我們的機器的記憶體還是比較小的,只有40G,設定的太小,可能會影響到虛擬記憶體的使用吧。
當大量的持續不斷的資料寫入cache記憶體中後,這些資料就被稱為髒資料。需要儘快將這些髒資料flush到磁碟中,釋放記憶體。
vm.dirty_background_ratio:這個引數指定了當檔案系統快取髒頁數量達到系統記憶體百分之多少時(如5%)就會觸發pdflush/flush/kdmflush等後臺回寫程序執行,將一定快取的髒頁非同步地刷入外存;
vm.dirty_ratio:這個引數則指定了當檔案系統快取髒頁數量達到系統記憶體百分之多少時(如10%),系統不得不開始處理快取髒頁(因為此時髒頁數量已經比較多,為了避免資料丟失需要將一定髒頁刷入外存);在此過程中很多應用程序可能會因為系統轉而處理檔案IO而阻塞。
這裡推薦將vm.dirty_background_ratio設定為5, vm.dirty_ratio有的人設定為10,但是我覺得太小了,還是預設的就可以了。
kafka叢集對網路的要求比較高,可以將socket的緩衝設定為原來的兩倍。
本文來自部落格園,作者:洛神灬殤,轉載請註明原文連結:https://www.cnblogs.com/liboware/p/16965859.html,任何足夠先進的科技,都與魔法無異。