本文做者是一位軟件工程師,他對20位開發人員和數據科學家使用Apache Kafka的方式進行了最大限度得深刻研究,最終將生產實踐環節須要注意的問題總結爲本文所列的20條建議。算法
Apache Kafka是一個廣受歡迎的分佈式流媒體平臺,New Relic、Uber以及Square等數千家公司都在使用它構建可擴展、高吞吐量、可靠的實時流媒體系統。例如,New Relic的Kafka集羣每秒處理超過1500萬條消息,總數據速率接近1 Tbps。sql
Kafka在應用程序開發人員和數據科學家中很是受歡迎,由於它極大簡化了數據流的處理過程。可是,Kafka在Scala上實踐會比較複雜。若是消費者沒法跟上數據流,而且消息在他們看到以前就消失了,那麼具備自動數據保留限制的高吞吐量發佈/訂閱模式並無多大用。一樣,若是託管數據流的系統沒法擴展以知足需求或者不可靠,也沒有什麼用。緩存
爲了下降這種複雜性,做者將可能的問題分爲4大類共20條,以方便用戶理解:網絡
Kafka是一種高效分佈式消息傳遞系統,可提供內置數據冗餘和彈性,同時保留高吞吐量和可擴展性。它包括自動數據保留限制,使其很是適合將數據視爲流的應用程序,而且還支持對鍵值對映射建模的「壓縮」流。架構
瞭解最佳實踐以前,你須要熟悉一些關鍵術語:負載均衡
第一部分:使用分區的最佳實踐!socket
在分區部分,咱們須要瞭解分區的數據速率,以確保擁有正確的保留空間。分區的數據速率是生成數據的速率。換句話說,它是平均消息大小乘以每秒消息數。數據速率決定了給定時間內所需的保留空間(以字節爲單位)。若是不知道數據速率,則沒法正確計算知足基本保留目標所需的空間大小。數據速率指定了單個消費者須要支持的最低性能而保證不會出現Lag。分佈式
除非有其餘架構需求,不然在寫入topic時使用隨機分區。當進行大規模操做時,分區之間的數據速率不都可能難以管理。須要注意如下三方面:性能
一、首先,「熱點」(更高吞吐量)分區的消費者必須處理比消費者羣組中其餘消費者更多的消息,這可能致使處理和網絡瓶頸。測試
二、其次,必須爲具備最高數據速率的分區調整topic保留空間大小,這可能會致使topic中其餘分區的磁盤使用量增長。
三、最後,在分區領導方面實現最佳平衡比簡單地擴展到全部 brokers更復雜。「熱點」分區的分量多是同一topic中另外一分區的10倍。
第二部分:使用消費者最佳實踐!
若是消費者運行的Kafka版本低於0.10,請升級。在0.8.x版本中,消費者使用Apache ZooKeeper進行消費者羣組協調,而且許多已知錯誤可能致使長期運行的平衡甚至是從新平衡算法的失敗(咱們稱之爲「從新平衡風暴」)。在從新平衡期間,將一個或多個分區分配給使用者羣組中的每一個使用者。在再平衡中,分區全部權在消費者中不斷變通,阻止任何消費者在消費方面取得實際進展。
四、調整消費者套接字緩衝區以進行高速獲取。在Kafka 0.10.x中,參數爲isreceive.buffer.bytes,默認爲64kB。在Kafka 0.8.x中,參數是socket.receive.buffer.bytes,默認爲100kB。對於高吞吐量環境,這兩個默認值都過小,特別是若是brocker和消費者之間的網絡帶寬延遲大於局域網(LAN)。對於延遲爲1毫秒或更長的高帶寬網絡(10 Gbps或更高),請考慮將套接字緩衝區設置爲8或16 MB。若是內存不足,請考慮1 MB,也可使用值-1,這樣底層操做系統能夠根據網絡條件調整緩衝區大小。可是,對於須要啓動「熱點」消費者的系統而言,自動調整的速度可能或比較慢。
五、設計高吞吐量消費者,以便在有保證的狀況下實施背壓,最好只消耗能夠有效處理的東西,而不是消耗太多,以致於過程中止,退出消費者羣組。 消費者應該使用固定大小的緩衝區(參見Disruptor模式),若是在Java虛擬機(JVM)中運行,最好是在堆外使用。固定大小的緩衝區將阻止消費者將大量數據拖到堆上,JVM花費全部時間來執行垃圾收集而不是作你想讓它處理的工做——處理消息。
六、在JVM上運行消費者時,請注意垃圾回收可能對消費者產生的影響。例如,垃圾收集較長時間暫停可能致使ZooKeeper會話或者消費者組失去平衡。對於brocker來講也是如此,若是垃圾收集暫停時間過長,則可能會從集羣中退出。
第三部分:使用生產者最佳實踐!
七、配置生產者等待確認。 這就是生產者如何知道消息實際已經發送到brocker上的分區。在Kafka 0.10.x中,設置爲acks; 在0.8.x中,它是request.required.acks。Kafka經過複製提供容錯功能,所以單個節點的故障或分區leader的更改不會影響可用性。若是將生產者配置爲沒有ack(也稱爲「fire and forget」),則消息可能會無聲地丟失。
八、配置生產者重試次數。默認值爲3,一般過低。正確的值取決於需求,對於沒法容忍數據丟失的應用程序,請考慮Integer.MAX_VALUE(其實是無窮大),這能夠防止leader分區的brocker沒法當即響應生產請求。
九、對於高吞吐量生產者,調整緩衝區大小,特別是buffer.memory和batch.size(以字節爲單位)。因爲batch.size是按分區設置的,所以生產者性能和內存使用量可與topic中的分區數相關聯。這裏的值取決於幾個因素:生產者數據速率(消息的大小和數量),生成的分區數以及可用的內存量。請記住,較大的緩衝區並不老是好的,若是生產者因爲某種緣由而停頓(例如,一個領導者經過確認響應較慢),在堆上緩存更多數據可能會致使更多垃圾收集。
十、制定應用程序跟蹤指標,例如生成的消息數,平均生成的消息大小和消耗的消息數。
第四部分:brocker最佳實踐!
十一、Topic須要brocker的內存和CPU資源,日誌壓縮須要brocker上的堆(內存)和CPU週期才能成功完成,而且失敗的日誌壓縮會使brocker處於無限增加的分區風險中。你能夠在brocker上使用tunelog.cleaner.dedupe.buffer.size和log.cleaner.threads,但請記住,這些值會影響brocker上的堆使用狀況。若是brocker拋出OutOfMemoryError異常,它將關閉並可能丟失數據。緩衝區大小和線程數將取決於要清理的主題分區數量以及這些分區中消息的數據速率和密鑰大小。從Kafka 0.10.2.1版本開始,監視日誌清理程序日誌文件以查找ERROR條目是檢測日誌清理程序線程問題的最可靠方法。
十二、監控brocker的網絡吞吐量。確保使用發送(TX)和接收(RX),磁盤I/O,磁盤空間和CPU使用率來執行此操做。容量規劃是維護集羣性能的關鍵部分。
1三、在集羣中的brocker之間分配分區leader,其須要大量的網絡I/O資源。例如,當使用複製因子3運行時,leader必須接收分區數據,並同步傳遞給全部副本,再傳輸給想要使用該數據的消費者。所以,在這個例子中,做爲領導者,在使用網絡I/O方面至少是follower的四倍,leader必須從磁盤讀取,follower只須要寫。
1四、不要忽略監視brocker的同步副本(ISR)縮減,重複不足的分區和不受歡迎的lesder。這些是集羣中潛在問題的跡象。例如,單個分區的頻繁ISR收縮可能代表該分區的數據速率超過了leader爲消費者和副本線程提供服務的能力。
1五、根據須要修改Apache Log4j屬性。Kafka代理日誌記錄可能會佔用過多磁盤空間。可是,不要徹底放棄日誌記錄,brocker日誌多是在事件發生後重建事件序列的最佳方式,有時也是惟一方式。
1六、禁用topic自動建立有關的明確策略,按期清理未使用的topic。例如,若是x天沒有看到任何消息,請考慮topic失效並將其從集羣中刪除,這樣能夠避免在集羣中建立必須管理的其餘元數據。
1七、對於持續的高吞吐量代理,請提供足夠的內存以免從磁盤系統讀取,應儘量直接從操做系統的文件系統緩存中提供分區數據。可是,這意味着必須確保消費者可以跟上,滯後的消費者將迫使brocker從磁盤讀取。
1八、對於具備高吞吐量服務級別目標(SLO)的大型集羣,請考慮將topic隔離到brocker子集。如何肯定要隔離的topic取決於業務需求,例如,若是有多個使用相同集羣的聯機事務處理(OLTP)系統,則將每一個系統的topic隔離到brocker的不一樣子集以幫助限制事件的潛在爆炸半徑。
1九、使用較新topic消息格式的舊客戶端(反之亦然)會在brocker客戶端轉換格式時對brocker程序施加額外負擔,儘量避免這種狀況。
20、不要認爲在本地臺式機上測試brocker表明在實際生產環境中的性能。使用複製因子1對分區的環回接口進行測試是與大多數生產環境徹底不一樣的拓撲。經過環回能夠忽略網絡延遲,而且在不涉及複製時,接收leader確認所需的時間可能會有很大差別。