目前,Apache Kafka已成為了應用服務間通信的常見選擇。Kafka不但能夠通過消息并行處理的方式來聚合日志,而且能夠應對低延遲、??高吞吐量??的需求。不過,對于許多微服務應用而言,Kafka的處理速度卻不一定夠快。
最近,異軍突起的開源式??Chronicle Queue??卻可以被用來開發一些只有微秒級延遲的消息傳遞框架。下面,我將和您深入地從微服務應用的吞吐量和可擴展性方面,比較Kafka與Chronicle Queue。
將延遲類比為距離
為了說明延遲,讓我們來做一個類比:通常,光線會以大約三分之二的光速在真空的光纖和銅線中傳輸,由此產生的瞬間延遲,可以被理解為信號在這段時間內所傳播的距離。
使用Chronicle的微服務延遲
Chronicle Queue的企業版(Enterprise)在500k msg/s的低吞吐量下,99%ile(正態分布中的平均值)的單個微服務的端到端延遲為3.69微秒。這等同于信號傳播了750米的距離,也就是普通人在倫敦市中心步行10分鐘的直線距離(請參見下圖)。
使用Kafka的微服務延遲
如果使用Kafka進行相同的測試,那么在100k 消息/秒(msg/s)的低吞吐量下,99%ile的單個微服務的端到端延遲約為2633微秒(如果是150k msg/s的話,延遲則會顯著增加)。這等同于信號傳播了526公里,也就是普通人花費100多個小時,從倫敦步行到達蘇格蘭的鄧弗里斯(Dumfries)。
日志聚合
針對日志聚合的需求,Kafka在最初的設計中就能夠提供多個連接器。因此,在典型的系統中,使用Kafka代替寫入日志文件,能夠達到提高性能、并顯著提高可管理性的效果。
測試場景
我在Ryzen 9 5950X服務器上部署并運行著Ubuntu 21.04。為了保持一致性,所有測試均會使用相同的MP600 PRO XT 2TB M.2 NVMe驅動。您可以通過鏈接--https://github.com/OpenHFT/Microservice-Benchmark,獲取基準測試的源代碼。
開源式Chronicle Queue v5.22ea14會使用Chronicle Wire進行序列化,并以500k msg/s的速度寫入。您可以針對單個生產者(Producer),以及下游的單個消費者(Consumer)進行如下配置:
-Dworkload=500kps.yaml chronicle.yaml
Chronicle Queue企業版v2.22ea72也使用Chronicle Wire進行序列化,并以500k msg/s的速度寫入。您可以針對異步緩沖區模式下的單個生產者,以及下游的單個消費者,進行如下配置:
-Dworkload=500kps.yaml chronicle-async.yaml
而帶有Jackson的Kafka 3.0.0在高吞吐量延遲的配置(主要是指linger.ms=1)下,可以100k msg/s的速度寫入。您可以針對JSON的4個分區和8個消費者,進行如下配置:
-Dworkload=100kps.yamlKafka.yaml
帶有Jackson的Kafka 3.0.0在高吞吐量延遲的配置(主要是指linger.ms=1)下,則可以250k msg/s的速度寫入。您可以針對JSON的4個分區和8個消費者,進行如下配置:
-Dworkload=250kps.yamlKafka.yaml
比較
分區和消費者的數量會在一定程度上影響到延遲。對于Chronicle Queue而言,在100k msg/s和500k msg/s下的性能表現大致相同。也就是說,Chronicle Queue的一項重要特征便是:性能基本不會受到發布者和消費者數量的影響。因此,我們針對500k msg/s的需求,采取一個發布者(publisher)、一個消費者(consumer)和一個微服務。
如果以500k msg/s對Kafka進行基準測試,則會導致消息出現排隊。而且基準運行的時間越長,延遲就會越明顯。例如,一旦出現2分鐘的突發流量峰值,就會導致接近1分鐘的延遲。
而如果想讓Kafka以250k msg/s的水平運行,則至少需要4個消費者。當然,如果設置8個消費者的基準,那么效果會更好,畢竟它會調用到Kafka的擴展技術。
發布延遲
上圖比較了兩者在發布上的延遲。僅從圖表看來,它們的差異可能十分明顯,但是在實際測試用例中,其間的延遲不會超過2.6微秒。就測試用例而言,其代碼如下。它在不同情況所發布的事件,都是512字節的JSON消息。而在消息被發送時,我們添加了兩個字段以進行跟蹤。
微服務消息傳輸
雖然我們在上面討論的發布時間、以及收發預序列化消息的時間,能夠很好地比較Kafka與Chronicle這兩個消息傳遞方案。但是這只是延遲難題的一部分。對于微服務而言,您需要知道從描述待處理事件的DTO(數據傳輸對象)開始,到下游消費者從原始微服務中讀取生成的DTO的時間。對此,我們需要通過針對微服務的基準測試,來獲悉如下發送相同事件的各個端到端階段的用時:
- 添加高精度的時間戳 (System.nanoTime())
- 序列化第一條消息
- 發布第一條消息
- 消費第一條消息
- 反序列化第一條消息
- 調用微服務
- 添加第二個高精度時間戳
- 序列化另一個主題/隊列上的第二條消息
- 發布第二條消息
- 消費第二條消息
- 反序列化第二條消息
- 記錄端到端延遲
注意:每條消息在生成時,都會創建第二條消息作為響應,因此與單跳躍(single-hop)消息傳遞基準相比,實際消息的數量會翻一倍。
Kafka在其已發布的基準測試中表現如何?
雖然在Kafka上發布事件通常需要幾微秒的時間,但端到端傳輸則會擴大到幾毫秒。根據Confluent發布的有關??單跳躍復制消息基準??的報告,有99%的端到端傳輸延遲為5毫秒。
而在我們的基準測試中,一臺主機上有2個跳躍點、序列化和反序列化。它們在100k msg/s輸出和100k msg/s返回的情況下,單個跳躍消息傳輸所出現的延遲與200k msg/s基本類似。
端到端延遲
為了進一步弄清楚到底Kafka與Chronicle在延遲上的差距有多大,我們需要通過下列圖表來進一步分析。為了便于比較,后一張圖表是前一張表放大10倍情況。
延遲達100微秒的情況
在保持與之前的規模相同的情況下,即使跨越了2個跳躍點(包括序列化),我們仍然可以看到:Chronicle Queue企業版保持著延遲的一致性;而開源式Chronicle Queue雖然在大部分時間內執行了相同的操作,但是它具有更高的延遲。這是因為Chronicle Queue企業版在開源的基礎上,包含了一些特定的功能,可以更好地控制異常值。當然,由于延遲相當高,因此您在下圖中看不到Kafka的相關曲線。
延遲達1000微秒的情況
下圖是放大10倍比例的情況。如您所見,雖然Chronicle Queue帶有更高的異常值,但是它們在99.99的分位上是相當一致的。同樣,Kafka的曲線仍然沒法顯示。
延遲達10,000微秒的情況
下圖是再放大10倍的情況。在這種規模下,我們無法看到Chronicle基準測試的太多細節,不過出現了兩種Kafka配置的典型延遲。特別是在100k msg/s(總共200k msg/s)的情況下,99%延遲約為2,630微秒。這與Confluent的5毫秒基準測試非常相似。
對延遲使用對數標度
對于較大范圍的數值,使用對數標度往往非常實用。如下圖所示,它雖然具有一定的可讀性,但是由于多數人不太習慣認讀對數比例圖表,因此他們很難解讀出延遲到底有多大的不同。
延遲到底有多大?
另一種可視化Kafka延遲的方法是繪制Kafka和Chronicle之間的延遲比率。下圖是Kafka在100k msg/s(最佳結果之一)和Chronicle Queue企業版在500k msg/s(即負載為Kafka的5倍)之間的延遲比率圖。在該基準測試中,即使其吞吐量只是Chronicle Queue的五分之一,Kafka仍然始終慢了至少680倍。
而且,為了讓Kafka能夠以100k msg/s的吞吐量實現其最低延遲,我們使用了4個分區和8個微服務。作為比較,Chronicle Queue在所有情況下都只需要1個足矣。
Chronicle Queue堆(Heap)的使用
我們讓Chronicle Queue以500k msg/s的消息寫入速度,并通過使用G1收集器和默認的GC參數,產生40 MB的峰值堆大小,并持續運行了5分鐘(總共3億條消息)的基準測試。其結果如下圖所示。當然,Chronicle Queue并沒有使用到標準的Java序列化功能。
Kafka內存的使用
我們讓Kafka以250k/s的消息寫入速度,使用2.87 GB的堆峰值,持續了10分鐘基準測試(總共3億條消息)。在啟動后,它觸發了2,410個暫停收集,以及182個并發循環收集。下圖展示了該測試在128 MB堆大小下運行時,所產生的超過139 k的GC。
小結
雖然Kafka是日志聚合的不錯選擇,但由于其相對較高的端到端延遲,對于許多涉及到微服務的用例而言,其延遲可能會比較明顯。開源式的Chronicle Queue在超過99.99%的時間內,都能夠實現低于100微秒的一致性延遲。而Kafka即使在吞吐量只有Chronicle的五分之一的情況下,也會有7毫秒的異常值。
譯者介紹
陳峻 (Julian Chen),51CTO社區編輯,具有十多年的IT項目實施經驗,善于對內外部資源與風險實施管控,專注傳播網絡與信息安全知識與經驗;持續以博文、專題和譯文等形式,分享前沿技術與新知;經常以線上、線下等方式,開展信息安全類培訓與授課。
原文標題:??Kafka vs Chronicle for Microservices??,作者:Peter Lawrey