一次Kafka記憶體洩露排查經過

阿維發表於2022-02-16

一、現象

服務部署後記憶體總體呈上升趨勢

  

二、排查過程

通過go tool pprof收集了三天記憶體資料

2月11號資料:

 

 

 

2月14號資料:

 

 

2月15號資料:

 

 

 

我們使用sarama客戶端連線kafka,可以看到newPartitionProducer持續增長,可定位到是kafka的問題。而newPartitionProducer是分割槽生產者,因此檢視分割槽相關的資料。

最近增加的topic:ai_face_process_topic,這個是AI換臉的,每生成一個視訊都要通過Kafka中轉訊息到視訊處理伺服器。

 

 

查閱資料庫看視訊生成記錄。2022.1.25上線到今天2022.2.15一共20天,只增長了701個視訊,平均每天35個視訊。

但這個topic有64個分割槽。這是因為視訊生成過程比較耗時,當時考慮到需要提高併發量,所以需要分割槽數比較多。

 

 

檢視sarama客戶端的API程式碼,給每個分割槽發訊息時會判斷這個分割槽的handler是否存在,不存在則建立。

sarama建立partition handler的關鍵程式碼:

     handler := tp.handlers[msg.Partition]
        if handler == nil {
            handler = tp.parent.newPartitionProducer(msg.Topic, msg.Partition)
            tp.handlers[msg.Partition] = handler
        }

 

 

且建立後需要手動close,否則記憶體一直佔用,這是官方說明:

 而我們使用sarama客戶端的producer是全域性的,一直不會close,所以會一直佔用記憶體。

 再看看我們使用sarama的partitioner是NewRandomPartitioner,即每條訊息隨機匹配到partition。

這樣,按照每天三十多的視訊生成量,出現前幾天新增分配二三十個handler,逐漸減少,直到分配完64個handler。

每個handler會分配8MB記憶體,也就出現了上面的記憶體資料:152MB,264MB,172MB。

 

三、結論與優化

記憶體增長几天穩定後則不會繼續增長。

 

其他分割槽數比較多的topic沒有觀察到記憶體持續增長情況是因為資料量比較大,服務啟動沒多久就分配完了每個分割槽的handler。

 

優化:

單個AI換臉視訊處理服務耗時較長,決定了我們需要比較大的併發量,所以後面分割槽數還可能增加。而64個分割槽已經使每個服務佔用64*8=504MB記憶體,嚴重影響擴充套件性。

因此後面ai_face_process_topic考慮遷移到redis做訊息中轉。

 

四、參考連結:

sarama API

githup sarama memory leak問題

kafka memory leak問題

 

相關文章