溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的

發(fā)布時(shí)間:2021-12-15 11:18:30 來源:億速云 閱讀:168 作者:柒染 欄目:大數(shù)據(jù)

這篇文章給大家介紹Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

Apache Kafka、Apache Pulsar和RabbitMQ都可以用作消息中間件平臺,可對比的項(xiàng)目非常多,但是通常最關(guān)心的就是性能。在本文中,將專注于系統(tǒng)的吞吐量延遲,因?yàn)檫@些是生產(chǎn)中事件流系統(tǒng)的主要性能指標(biāo)。吞吐量測試尤其可以衡量每個(gè)系統(tǒng)在利用硬件(特別是磁盤和CPU)方面的效率。延遲測試可衡量每個(gè)系統(tǒng)與實(shí)時(shí)消息傳遞之間的接近程度,其中包括高達(dá)p99.9%的尾部延遲,這是實(shí)時(shí)和關(guān)鍵業(yè)務(wù)系統(tǒng)以及微服務(wù)架構(gòu)的核心要求。

從測試結(jié)果來看,Kafka提供了最佳的吞吐量,同時(shí)提供最低的端到端延遲,最高可達(dá)p99.9%。在較低的吞吐量下,RabbitMQ傳遞消息的延遲非常低。

Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的


KafkaPulsarRabbitMQ(鏡像)
峰值吞吐量605MB/s305MB/s38MB/s
p99延遲(毫秒)5毫秒(200MB/s負(fù)載)25毫秒(200MB/s負(fù)載)1ms*(減少至30MB/s的負(fù)載)

注意:RabbitMQ延遲在吞吐量高于30MB/s時(shí)會顯著上升。此外,在更高的吞吐量下,鏡像的影響非常明顯,而僅使用傳統(tǒng)隊(duì)列而不進(jìn)行鏡像,則可以實(shí)現(xiàn)更好的延遲。

本文的結(jié)構(gòu)會首先介紹使用的測試框架,然后介紹測試平臺和工作負(fù)載。最后將使用各種系統(tǒng)和應(yīng)用指標(biāo)對結(jié)果進(jìn)行解釋。所有這些都是開源的,因此好奇的開發(fā)者可以自己復(fù)制結(jié)果,也可以更深入地研究所收集的Prometheus指標(biāo)。與大多數(shù)基準(zhǔn)測試一樣,性能測試是基于一組特定的工作負(fù)載/配置的。當(dāng)然開發(fā)者也可以使用自己的工作負(fù)載/配置進(jìn)行比較,以了解如何切換為生產(chǎn)環(huán)境。

背景

首先簡要介紹每個(gè)系統(tǒng),以了解它們的高級設(shè)計(jì)和架構(gòu),并研究每個(gè)系統(tǒng)所做出的取舍。

Kafka是一個(gè)開源的分布式事件流平臺,是Apache軟件基金會五個(gè)最活躍的項(xiàng)目之一。Kafka的核心是一個(gè)可復(fù)制的、分布式的、持久化的提交日志,用于為事件驅(qū)動的微服務(wù)或大規(guī)模流處理應(yīng)用提供支持。客戶端直接向/從代理集群生成或消費(fèi)事件,代理集群將事件持久化到基礎(chǔ)文件系統(tǒng),并且還自動在集群內(nèi)同步或異步復(fù)制事件,以實(shí)現(xiàn)容錯(cuò)和高可用性。

Pulsar是一個(gè)開源的分布式發(fā)布/訂閱消息系統(tǒng),最初是為隊(duì)列場景而設(shè)計(jì)的。最近,它還添加了事件流功能。Pulsar被設(shè)計(jì)為(幾乎)無狀態(tài)代理實(shí)例層,這些實(shí)例連接到單獨(dú)的BookKeeper實(shí)例層,該實(shí)例實(shí)際負(fù)責(zé)讀/寫并有選擇地持久化存儲/復(fù)制消息。同類系統(tǒng)中Pulsar并不是唯一的,還有例如Apache DistributedLog和Pravega,它構(gòu)建于BookKeeper之上,可以提供一些類似Kafka的事件流功能。

BookKeeper是一個(gè)開源分布式存儲服務(wù),最初設(shè)計(jì)為Hadoop NameNode的預(yù)寫日志。它在稱為bookies服務(wù)器實(shí)例之間以賬本的形式提供消息的持久化存儲。每個(gè)bookie出于恢復(fù)的目的將每個(gè)消息同步寫入本地日志,然后異步寫入其本地索引存儲中。與Kafka代理不同,bookies不會相互通信,而BookKeeper客戶端負(fù)責(zé)使用仲裁協(xié)議在bookies之間復(fù)制消息。

RabbitMQ是一個(gè)開源的傳統(tǒng)消息中間件,該中間件實(shí)現(xiàn)了AMQP消息標(biāo)準(zhǔn),可滿足低延遲隊(duì)列場景的需要。RabbitMQ由一組代理進(jìn)程組成,這些代理進(jìn)程托管用于將消息發(fā)布到其中的交換器以及用于消費(fèi)消息的隊(duì)列。可用性和持久性是所提供的各種隊(duì)列類型的屬性。傳統(tǒng)隊(duì)列提供最少的可用性保證。傳統(tǒng)鏡像隊(duì)列將消息復(fù)制到其他代理,并提高可用性。通過最近引入的仲裁隊(duì)列可以提供更強(qiáng)的持久性,但是會降低性能。由于本文關(guān)注性能,因此將評估限制為傳統(tǒng)隊(duì)列和鏡像隊(duì)列。

分布式系統(tǒng)的持久性

單節(jié)點(diǎn)存儲系統(tǒng)(例如RDBMS)依賴于對磁盤的全同步寫入來確保最大的持久性。但是在分布式系統(tǒng)中,持久性通常來自復(fù)制,數(shù)據(jù)的多個(gè)副本相互獨(dú)立。全同步數(shù)據(jù)只是在故障確實(shí)發(fā)生時(shí)減少故障影響的一種方式(例如更頻繁地進(jìn)行同步可能會縮短恢復(fù)時(shí)間)。相反,如果足夠多的副本失敗,則無論全同步與否,分布式系統(tǒng)都可能無法使用。因此,是否進(jìn)行全同步只是一個(gè)問題,即每個(gè)系統(tǒng)選擇依賴于什么來進(jìn)行復(fù)制設(shè)計(jì)。盡管有些緊密依賴于寫入磁盤的數(shù)據(jù),因此每次寫入都需要同步,但其他一些則在設(shè)計(jì)中處理了這種情況。

Kafka的復(fù)制協(xié)議經(jīng)過精心設(shè)計(jì),可通過跟蹤已同步到磁盤的內(nèi)容和未同步到磁盤的內(nèi)容來確保一致性和持久性,而無需全同步寫盤。通過少做一些假設(shè),Kafka可以處理范圍更廣的故障,例如文件系統(tǒng)級損壞或意外的磁盤資源調(diào)配,并且不會將不知道的數(shù)據(jù)的正確性視為理所當(dāng)然。Kafka還能夠利用操作系統(tǒng)來批量寫入磁盤,以提高性能。

目前無法明確確定BookKeeper是否在不全同步每個(gè)寫入的情況下提供相同的一致性保證,特別是在沒有同步磁盤持久性的情況下是否可以依靠復(fù)制來實(shí)現(xiàn)容錯(cuò)。根據(jù)檢查以及BookKeeper實(shí)現(xiàn)了分組的全同步算法這一事實(shí),可以認(rèn)為它確實(shí)依賴于全同步寫入來確保其正確性,但是這個(gè)結(jié)論還需進(jìn)一步確認(rèn)。

由于這可能是一個(gè)有爭議的話題,因此測試過程中在兩種情況下都給出了結(jié)果,以確保盡可能公平和完整,盡管使用全同步運(yùn)行Kafka極為罕見,也沒有必要。

基準(zhǔn)測試框架

對于任何測試,大家都會關(guān)注使用了什么框架,以及它是否公平。為此,本次測試選擇了OpenMessaging Benchmark Framework(OMB),該框架最初是由Pulsar貢獻(xiàn)者開發(fā)的。OMB入門容易,它具有基本的工作負(fù)載規(guī)范,測試結(jié)果的指標(biāo)收集/報(bào)告匯總,對3個(gè)選定消息系統(tǒng)的支持以及針對每個(gè)系統(tǒng)定制的模塊化云部署工作流。但需要注意的是,Kafka和RabbitMQ的實(shí)現(xiàn)確實(shí)存在一些問題,影響了這些測試的公平性和可重復(fù)性,因此本次測試做了一些修正,相關(guān)的代碼可從這里獲得。

OMB框架調(diào)整

測試軟件平臺已升級到Java 11、Kafka 2.6、RabbitMQ 3.8.5和Pulsar 2.6(當(dāng)前的最新版本),通過使用Grafana/Prometheus監(jiān)控堆棧,跨消息系統(tǒng)、JVM、Linux、磁盤、CPU和網(wǎng)絡(luò)捕獲指標(biāo),顯著增強(qiáng)了跨3個(gè)系統(tǒng)的監(jiān)控功能。這對于不僅能夠報(bào)告結(jié)果而且能夠解釋結(jié)果至關(guān)重要。本次測試增加了對僅生產(chǎn)者測試和僅消費(fèi)者測試的支持,并支持生成/排出積壓,同時(shí)還修復(fù)了當(dāng)主題數(shù)小于生產(chǎn)者工作節(jié)點(diǎn)數(shù)時(shí)生產(chǎn)者比率計(jì)算的一個(gè)嚴(yán)重錯(cuò)誤。

OMB Kafka驅(qū)動調(diào)整

本次測試修復(fù)了Kafka驅(qū)動中的一個(gè)嚴(yán)重Bug,該Bug使Kafka生產(chǎn)者無法使用TCP連接,并限制了每個(gè)工作實(shí)例的單個(gè)連接的瓶頸。與其他系統(tǒng)相比,此修復(fù)使Kafka的數(shù)量合理,即它們現(xiàn)在都使用相同數(shù)量的TCP連接與各自的代理進(jìn)行通信。還修復(fù)了Kafka消費(fèi)者驅(qū)動中的一個(gè)嚴(yán)重Bug,該Bug中偏移量的提交過于頻繁且同步導(dǎo)致性能下降,而其他系統(tǒng)則異步進(jìn)行。測試還調(diào)整了Kafka消費(fèi)者獲取大小和復(fù)制線程數(shù),以消除高吞吐量時(shí)消息獲取的瓶頸,并配置與其他系統(tǒng)同等的代理。

OMB RabbitMQ驅(qū)動調(diào)整

測試增強(qiáng)了RabbitMQ以使用主鍵路由和可配置的交換類型(DIRECTTOPIC交換),并且還修復(fù)了RabbitMQ集群設(shè)置部署工作流中的一個(gè)Bug。引入了主鍵路由來模仿每個(gè)主題的分區(qū)概念,等同于Kafka和Pulsar上的設(shè)置。還為RabbitMQ部署添加了TimeSync工作流程,用于在客戶端實(shí)例之間同步時(shí)間,以進(jìn)行精確的端到端延遲測量。此外還修復(fù)了RabbitMQ驅(qū)動中的另一個(gè)Bug,以確保準(zhǔn)確的端到端延遲測量。

OMB Pulsar驅(qū)動調(diào)整

對于OMB Pulsar驅(qū)動,測試添加了為Pulsar生產(chǎn)者指定最大批處理大小的功能,并關(guān)閉了任何全局限制,這些限制可能會人為地在更高的目標(biāo)速率下限制跨分區(qū)生產(chǎn)者隊(duì)列的吞吐量,測試不需要對Pulsar驅(qū)動進(jìn)行任何其他重大更改。

測試平臺

OMB包含基準(zhǔn)的測試平臺定義(實(shí)例類型和JVM配置)和負(fù)載驅(qū)動配置(生產(chǎn)者/消費(fèi)者配置以及服務(wù)器端配置),這些將被用作測試的基礎(chǔ)。所有測試均部署4個(gè)工作實(shí)例來驅(qū)動負(fù)載,3個(gè)代理/服務(wù)器實(shí)例,1個(gè)監(jiān)控實(shí)例,以及可選的用于Kafka和Pulsar的3實(shí)例Apache ZooKeeper集群。在嘗試了幾種實(shí)例類型之后,測試選擇了經(jīng)過網(wǎng)絡(luò)/存儲優(yōu)化的Amazon EC2實(shí)例類型,具有足夠的CPU內(nèi)核和網(wǎng)絡(luò)帶寬來支持磁盤I/O綁定的工作負(fù)載。下面會介紹對這些基準(zhǔn)配置進(jìn)行的所有更改,以及進(jìn)行不同測試的過程。

磁盤

具體來說,測試使用i3en.2xlarge8核、64 GB內(nèi)存、2x2,500GB NVMe固態(tài)盤)來實(shí)現(xiàn)25Gbps的高網(wǎng)絡(luò)傳輸帶寬,以確保測試不受網(wǎng)絡(luò)限制。這意味著測試將測量相應(yīng)的最大服務(wù)器性能指標(biāo),而不僅僅是網(wǎng)絡(luò)的速度。i3en.2xlarge實(shí)例在2個(gè)磁盤之間支持高達(dá)655MB/s的寫入吞吐量,這足以使服務(wù)器承受壓力。根據(jù)常規(guī)建議以及原始OMB設(shè)置,Pulsar使用其中一個(gè)磁盤進(jìn)行日志存儲,并使用另一個(gè)磁盤進(jìn)行數(shù)據(jù)存儲,沒有對Kafka和RabbitMQ的磁盤設(shè)置進(jìn)行任何更改。

Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的

圖1:建立兩個(gè)磁盤上i3en.2xlarge實(shí)例的最大磁盤帶寬,使用Linux的dd命令進(jìn)行測試,作為吞吐量測試的基準(zhǔn)。

磁盤 1
dd if=/dev/zero of=/mnt/data-1/test bs=1M count=65536 oflag=direct
65536+0 records in
65536+0 records out
68719476736 bytes (69 GB) copied, 210.278 s, 327 MB/s

磁盤 2
dd if=/dev/zero of=/mnt/data-2/test bs=1M count=65536 oflag=direct
65536+0 records in
65536+0 records out
68719476736 bytes (69 GB) copied, 209.594 s, 328 MB/s

操作系統(tǒng)調(diào)整

此外,對于這3套系統(tǒng),使用tuned-adm配置文件對操作系統(tǒng)的延遲性能進(jìn)行了優(yōu)化,該配置文件禁用了磁盤和網(wǎng)絡(luò)調(diào)度程序的任何動態(tài)調(diào)優(yōu)機(jī)制,并使用性能調(diào)控器進(jìn)行CPU頻率調(diào)整。它將p狀態(tài)標(biāo)記為每個(gè)內(nèi)核的最高頻率,并將I/O調(diào)度程序設(shè)置為截止時(shí)間,以提供可預(yù)測的磁盤請求延遲上限。最后還對內(nèi)核中的電源管理服務(wù)質(zhì)量(QoS)進(jìn)行了優(yōu)化,以實(shí)現(xiàn)性能優(yōu)于節(jié)能。

內(nèi)存

與OMB中的默認(rèn)實(shí)例相比,i3en.2xlarge測試實(shí)例擁有幾乎一半的物理內(nèi)存(64GB122GB)。調(diào)整Kafka和RabbitMQ與測試實(shí)例兼容非常簡單,兩者都主要依賴于操作系統(tǒng)的頁面緩存,隨著新實(shí)例的增加,頁面緩存會自動縮小。

但是,Pulsar代理和BookKeeper的bookies都依賴堆外/直接內(nèi)存進(jìn)行緩存,測試為這兩個(gè)單獨(dú)的進(jìn)程調(diào)整了JVM堆/最大直接內(nèi)存,以便在i3en.2xlarge實(shí)例上正常工作。具體地說,就是將堆大小從每個(gè)24GB(在原始OMB配置中)減半到12GB,在兩個(gè)進(jìn)程和操作系統(tǒng)之間按比例分配可用物理內(nèi)存。

在測試中遇到了java.lang.OutOfMemoryError: Direct buffer memory,在高目標(biāo)吞吐量時(shí)直接出現(xiàn)該錯(cuò)誤,如果堆大小再小,則會導(dǎo)致bookies完全崩潰。這是使用堆外內(nèi)存的系統(tǒng)所面臨的典型內(nèi)存優(yōu)化問題。雖然直接字節(jié)緩沖區(qū)可以改善Java GC,但是大幅度優(yōu)化仍然具有挑戰(zhàn)。

吞吐量測試

首先測試的是,在網(wǎng)絡(luò)、磁盤、CPU和內(nèi)存資源相同的情況下,每個(gè)系統(tǒng)可以達(dá)到的峰值穩(wěn)定吞吐量。峰值穩(wěn)定吞吐量的定義是最高的平均生產(chǎn)者吞吐量,在此水平下,消費(fèi)者可以在不增加積壓的情況下保持穩(wěn)定。

全同步的效果

如前所述,Apache Kafka的默認(rèn)建議配置是使用底層操作系統(tǒng)規(guī)定的頁面緩存刷新策略將消息刷新/全同步到磁盤(而不是全同步每條消息),并依靠復(fù)制來實(shí)現(xiàn)持久性。從根本上說,這提供了一種簡單有效的方法來攤銷Kafka生產(chǎn)者采用的不同批次大小的成本,以在所有條件下實(shí)現(xiàn)最大可能的吞吐量。如果將Kafka配置為在每次寫入時(shí)進(jìn)行全同步,則通過強(qiáng)制執(zhí)行全同步系統(tǒng)調(diào)用將人為地阻礙性能,而沒有任何其他好處。

也就是說,鑒于要討論這兩種情況的結(jié)果,仍然有必要了解全同步對Kafka中每次寫入的影響。各種生產(chǎn)者批次大小對Kafka吞吐量的影響如下圖所示。在達(dá)到“最佳點(diǎn)”之前,吞吐量隨著批次大小的增加而增加,在“最佳點(diǎn)”,批次大小足夠大,底層磁盤會處于滿載狀態(tài)。將每個(gè)消息同步到Kafka上的磁盤(圖2中的橙色條)會產(chǎn)生更大批量的類似結(jié)果。請注意,這些結(jié)果僅在本測試平臺的SSD上得到了驗(yàn)證。Kafka確實(shí)充分利用了所有批處理大小的底層磁盤,或者在較低的批處理大小下最大化IOPS,或者在更高的批處理大小下最大化磁盤吞吐量,即使在強(qiáng)制對每個(gè)消息進(jìn)行全同步時(shí)也是如此。 Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的

圖2:批次大小對Kafka吞吐量(消息/s)的影響,綠色條代表關(guān)閉全同步(默認(rèn)),橙色條代表啟用全同步。

就是說,從上表中可以明顯看出,使用默認(rèn)的同步設(shè)置(綠色條)可以使Kafka代理更好地管理頁面刷新,從而總體上提供更好的吞吐量。特別是,對于較低的生產(chǎn)者批次大小(1KB和10KB),使用默認(rèn)同步設(shè)置的吞吐量要比全同步模式高約3-5倍。但是,對于較大的批次(100KB和1MB),將分?jǐn)側(cè)降某杀?,吞吐量與默認(rèn)同步模式大體相當(dāng)。

Pulsar在生產(chǎn)者上實(shí)現(xiàn)了類似的批處理,并跨bookies對生產(chǎn)的消息進(jìn)行定額復(fù)制。BookKeeper的bookies在應(yīng)用級別實(shí)現(xiàn)對磁盤的分組提交/同步,以最大化磁盤吞吐量。默認(rèn)情況下BookKeeper (由bookie的配置項(xiàng)journalSyncData=true控制)以全同步模式寫入磁盤。

為了覆蓋所有場景,還測試了BookKeeper上配置了journalSyncData=false的情況,以分別與Kafka做對比。但是在BookKeeper的bookies上遇到了較大的延遲和不穩(wěn)定性,這表明與刷新有關(guān)的排隊(duì)。測試還使用Pulsar附帶的pulsar-perf工具驗(yàn)證了相同的行為。據(jù)了解這是個(gè)Bug,因此后續(xù)將其從測試中排除。盡管如此,鑒于journalSyncData=true時(shí)可以看到磁盤的吞吐量已達(dá)到極限,因此認(rèn)為這不會影響最終結(jié)果。

Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的

圖3:Pulsar與BookKeeper的journalSyncData=false性能說明,顯示了吞吐量下降和延遲峰值

Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的

圖4:BookKeeper日志回調(diào)隊(duì)列的增長與journalSyncData=false

RabbitMQ與持久化隊(duì)列綁定,該持久化隊(duì)列當(dāng)且僅當(dāng)尚未消費(fèi)消息時(shí)才將消息保存到磁盤。與Kafka和Pulsar不同,RabbitMQ不支持再次讀取舊消息。從持久性的角度來看,測試表明消費(fèi)者與生產(chǎn)者保持同步,因此沒有注意到對磁盤的任何寫入。測試還通過在3個(gè)代理的集群中使用鏡像隊(duì)列,使得RabbitMQ提供了與Kafka和Pulsar相同的可用性保證。

測試配置

測試是根據(jù)以下原則和預(yù)期保證設(shè)計(jì)的:

  • 消息被復(fù)制3份,以實(shí)現(xiàn)容錯(cuò)功能(具體下面會詳述);

  • 所有3個(gè)系統(tǒng)都啟用了批處理以優(yōu)化吞吐量,最多可批處理1MB的數(shù)據(jù),最多10ms;

  • Pulsar和Kafka在一個(gè)主題上配置了100個(gè)分區(qū);

  • RabbitMQ不支持主題中的分區(qū),為了匹配Kafka和Pulsar的設(shè)置,聲明了一個(gè)單一直接交換(等同于主題)和鏈接隊(duì)列(等同于分區(qū)),具體下面會詳述。

OMB使用自動速率發(fā)現(xiàn)算法,該算法通過以幾種速率探測積壓來動態(tài)得出目標(biāo)生產(chǎn)者的吞吐量。在許多情況下,會看到確定速率從2.0消息/秒急劇上升到500,000消息/秒。這些嚴(yán)重?fù)p害了測試的可重復(fù)性和保真度。因此在本次測試中明確地配置了目標(biāo)吞吐量而沒有使用此功能,并在每秒10K、50K、100K、200K、500K和100萬個(gè)生產(chǎn)者消息中穩(wěn)定增加了目標(biāo)吞吐量,其中4個(gè)生產(chǎn)者和4個(gè)消費(fèi)者使用1KB的消息。然后觀察每個(gè)系統(tǒng)針對不同配置提供穩(wěn)定的端到端性能的最大速率。

吞吐量結(jié)果

從結(jié)果可以發(fā)現(xiàn)Kafka提供了3個(gè)系統(tǒng)中的最高吞吐量,后續(xù)將在下面的每個(gè)系統(tǒng)中更詳細(xì)地研究這些結(jié)果。

Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的

圖5:所有3個(gè)系統(tǒng)的峰值穩(wěn)定吞吐量的比較:100個(gè)主題分區(qū)和1KB消息,使用4個(gè)生產(chǎn)者和4個(gè)消費(fèi)者

Kafka配置為使用batch.size=1MB以及linger.ms=10,供生產(chǎn)者高效批量寫入代理。另外,生產(chǎn)者配置了acks=all以及min.insync.replicas=2,以確保每個(gè)消息向生產(chǎn)者確認(rèn)之前都已復(fù)制到至少2個(gè)代理中。測試發(fā)現(xiàn),Kafka能夠充分利用每個(gè)代理上的2個(gè)磁盤,這是存儲系統(tǒng)的理想結(jié)果。有關(guān)詳細(xì)信息,請參見Kafka的測試驅(qū)動配置。

Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的

圖6:使用默認(rèn)的推薦全同步設(shè)置的Kafka性能。該圖顯示了Kafka代理上的I/O利用率以及相應(yīng)的生產(chǎn)者/消費(fèi)者吞吐量(來源:Prometheus節(jié)點(diǎn)指標(biāo))。有關(guān)詳細(xì)信息,請參見原始結(jié)果。

另外,還使用另一種配置對Kafka進(jìn)行了基準(zhǔn)測試,即使用flush.messages=1flush.ms=0在確認(rèn)寫入之前將所有消息同步到所有副本上的磁盤上。結(jié)果顯示在下圖中,非常接近默認(rèn)配置:

Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的

圖7:Prometheus節(jié)點(diǎn)指標(biāo)顯示了Kafka代理上的I/O利用率以及相應(yīng)的生產(chǎn)者/消費(fèi)者吞吐量。有關(guān)詳細(xì)信息,請參見原始結(jié)果。

Pulsar的生產(chǎn)者在排隊(duì)產(chǎn)生請求方面的方式與Kafka不同。具體來說,它在內(nèi)部每個(gè)分區(qū)都有對應(yīng)的生產(chǎn)者隊(duì)列,以及這些隊(duì)列大小的限制,這些限制對來自給定生產(chǎn)者的所有分區(qū)的消息數(shù)量設(shè)置了上限。為了避免Pulsar生產(chǎn)者限制發(fā)送的消息數(shù)量,測試將每個(gè)分區(qū)和全局限制都設(shè)置為無窮大,同時(shí)與基于1MB字節(jié)的批處理限制相匹配。

.batchingMaxBytes(1048576) // 1MB
.batchingMaxMessages(Integer.MAX_VALUE)
.maxPendingMessagesAcrossPartitions(Integer.MAX_VALUE);

針對Pulsar,還設(shè)置了更高的基于時(shí)間的批處理限制:batchingMaxPublishDelayMs=50,以確保批處理主要基于字節(jié)數(shù)限制。測試通過不斷增加該值,直至對Pulsar最終達(dá)到的峰值穩(wěn)定吞吐量沒有可測量的影響,得出了該值。對于復(fù)制配置,測試使用ensembleSize=3,writeQuorum=3,ackQuorum=2,等效于Kafka的配置方式。有關(guān)詳細(xì)信息,請參見Pulsar的測試驅(qū)動配置。

通過BookKeeper的設(shè)計(jì),即bookies將數(shù)據(jù)寫入本地的日志和賬本中,可以看到,峰值穩(wěn)定吞吐量實(shí)際上是Kafka的一半。這種基本的設(shè)計(jì)選擇會對吞吐量產(chǎn)生深遠(yuǎn)的負(fù)面影響,這直接影響成本。一旦BookKeeper的bookies上的日志磁盤完全飽和,Pulsar的生產(chǎn)率就將被限制。

Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的

圖8:Prometheus節(jié)點(diǎn)度量指標(biāo)顯示Pulsar的BookKeeper日志磁盤已用完,并在BookKeeper的bookies中測量了所產(chǎn)生的吞吐量。有關(guān)詳細(xì)信息,請參見原始結(jié)果。

為了進(jìn)一步驗(yàn)證這一點(diǎn),測試還將BookKeeper配置為在RAID0中使用2個(gè)磁盤,這為BookKeeper提供了在2個(gè)磁盤上分別寫入日志和賬本的機(jī)會。這時(shí)會看到,Pulsar最大化了磁盤的組合吞吐量(~650MB/s),但仍限于峰值穩(wěn)定吞吐量的~340MB/s。

Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的

圖9:Prometheus節(jié)點(diǎn)指標(biāo)顯示RAID0配置使BookKeeper日志磁盤仍然用盡

Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的

圖10:Prometheus節(jié)點(diǎn)指標(biāo)顯示RAID0磁盤已用完,并在Pulsar代理處測量了所產(chǎn)生的吞吐量。有關(guān)詳細(xì)信息,請參見原始結(jié)果。

Pulsar具有分層架構(gòu),可將BookKeeper的bookies(存儲)與Pulsar代理(用于存儲的緩存/代理)分開。為了完整起見,測試還在上面的分層部署中運(yùn)行了吞吐量測試,該部署將Pulsar代理移動到了另外3個(gè)經(jīng)過計(jì)算優(yōu)化的實(shí)例c5n.2xlarge(帶有8核、21GB內(nèi)存、最高25Gbps網(wǎng)絡(luò)帶寬、基于EBS的存儲),而BookKeeper節(jié)點(diǎn)保留在經(jīng)過存儲優(yōu)化的i3en.2xlarge實(shí)例上。在這種特殊設(shè)置下,總共為Pulsar和BookKeeper提供了6個(gè)實(shí)例/資源,這比給Kafka和RabbitMQ提供了2倍的CPU資源和33%的額外內(nèi)存。

即使在高吞吐量的情況下,系統(tǒng)也大部分受I/O約束,測試沒有發(fā)現(xiàn)此設(shè)置有任何改進(jìn)。有關(guān)此特定場景的完整結(jié)果,請參見下表。實(shí)際上,Pulsar的2層架構(gòu)似乎沒有任何真正的CPU瓶頸,只會增加更多的開銷,即2個(gè)JVM占用了更多的內(nèi)存,網(wǎng)絡(luò)傳輸增加了2倍,并且系統(tǒng)架構(gòu)中有更多的組件。因此可以認(rèn)為當(dāng)網(wǎng)絡(luò)受到限制時(shí)(不同于本次測試提供了過多的網(wǎng)絡(luò)帶寬),Pulsar的2層架構(gòu)將以2倍的速度消耗網(wǎng)絡(luò)資源,從而導(dǎo)致性能下降。

Pulsar部署模式峰值生產(chǎn)者吞吐量(MB/s)
分層305.73
共存305.69

與Kafka和Pulsar不同,RabbitMQ在主題中沒有分區(qū)的概念。相反,RabbitMQ使用交換器將消息路由到鏈接的隊(duì)列,使用頭屬性(頭交換)、路由鍵(直接和主題交換)或綁定(扇出交換),消費(fèi)者可以從中處理消息。為了匹配工作負(fù)載的設(shè)置,本次測試聲明了一個(gè)直接交換(等同于主題)和鏈接隊(duì)列(等同于分區(qū)),每一個(gè)都專門用于服務(wù)特定的路由鍵。測試讓生產(chǎn)者為所有路由鍵(輪詢)和每個(gè)隊(duì)列對應(yīng)的消費(fèi)者生成消息。本次測試還使用了社區(qū)建議的最佳實(shí)踐對RabbitMQ進(jìn)行了優(yōu)化:

  • 啟用復(fù)制(隊(duì)列被復(fù)制到集群中的所有節(jié)點(diǎn));

  • 禁用消息持久性(隊(duì)列僅在內(nèi)存中);

  • 啟用了消費(fèi)者自動確認(rèn);

  • 跨代理的負(fù)載均衡隊(duì)列;

  • RabbitMQ每個(gè)隊(duì)列使用專用內(nèi)核,因此有24個(gè)隊(duì)列(8個(gè)vCPU x 3個(gè)代理)。

RabbitMQ在復(fù)制開銷方面表現(xiàn)不佳,這嚴(yán)重降低了系統(tǒng)的吞吐量。測試注意到在此工作負(fù)載期間,所有節(jié)點(diǎn)都受CPU約束(請參見下圖中的y軸綠線),幾乎沒有余地用于代理任何其他消息。有關(guān)詳細(xì)信息,請參見RabbitMQ測試驅(qū)動配置。

Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的

圖11:RabbitMQ吞吐量 + CPU使用率。有關(guān)詳細(xì)信息,請參見原始結(jié)果。

延遲測試

鑒于流處理和事件驅(qū)動的架構(gòu)日益普及,消息系統(tǒng)的另一個(gè)關(guān)鍵是消息從生產(chǎn)者到系統(tǒng)再到消費(fèi)者的管道的端到端延遲,因此本次測試在三個(gè)系統(tǒng)上以每個(gè)系統(tǒng)可以維持的最高穩(wěn)定吞吐量,而不過載的前提下對此進(jìn)行了對比。

為了優(yōu)化延遲,本次測試更改了所有系統(tǒng)上的生產(chǎn)者配置,以最多僅1毫秒(而不是用于吞吐量測試的10毫秒)批處理消息,并且還使每個(gè)系統(tǒng)保持默認(rèn)建議配置,同時(shí)確??捎眯浴afka配置為使用其默認(rèn)的全同步設(shè)置(即關(guān)閉全同步),RabbitMQ配置為對隊(duì)列鏡像的同時(shí)不保存消息?;诜磸?fù)運(yùn)行,本次測試選擇以200K消息/秒或200MB/s的速度對Kafka和Pulsar進(jìn)行對比,該速度低于此測試平臺上300MB/s的單磁盤吞吐量限制,最后可以看到在吞吐量超過30K消息/秒時(shí),RabbitMQ將面臨CPU瓶頸。

延遲測試結(jié)果

Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的

圖12:高可用性配置的標(biāo)準(zhǔn)模式的端到端延遲,在Kafka和Pulsar上測量值為200K消息/秒(1KB消息大?。?,在RabbitMQ上僅為30K消息/秒,因其無法維持更高的負(fù)載。注意:延遲(ms)是越低越好。

Kafka始終保持比Pulsar更低的延遲,RabbitMQ實(shí)現(xiàn)了3個(gè)系統(tǒng)中最低的延遲,但由于垂直擴(kuò)展性有限,因此吞吐量低很多。由于測試是有意設(shè)置的,因此對于每個(gè)系統(tǒng)消費(fèi)者始終能夠與生產(chǎn)者保持同步,幾乎所有讀取都從這3個(gè)系統(tǒng)的緩存/內(nèi)存中獲得。

Kafka的大部分性能可歸因于充分優(yōu)化的消費(fèi)者讀取實(shí)現(xiàn),該實(shí)現(xiàn)基于有效的數(shù)據(jù)組織而沒有任何額外的開銷。Kafka充分利用Linux頁面緩存和零復(fù)制機(jī)制來避免將數(shù)據(jù)復(fù)制到用戶空間中。通常,許多系統(tǒng)(例如數(shù)據(jù)庫)已經(jīng)建立了應(yīng)用級緩存,從而為它們提供了更大的靈活性來支持隨機(jī)的讀/寫負(fù)載。但是,對于消息系統(tǒng),依靠頁面緩存是一個(gè)不錯(cuò)的選擇,因?yàn)榈湫偷呢?fù)載會執(zhí)行順序的讀/寫操作。Linux內(nèi)核已經(jīng)進(jìn)行了多年優(yōu)化,以智能地檢測這些模式,并采用諸如預(yù)讀的技術(shù)來大大提高讀取性能。同樣,基于頁面緩存構(gòu)建允許Kafka使用基于sendfile的網(wǎng)絡(luò)傳輸,可避免其他數(shù)據(jù)副本。為了與吞吐量測試保持一致,還測試了Kafka的全同步模式。

Pulsar與Kafka相比采用了不同的緩存方式,其中一些源于BookKeeper中的核心設(shè)計(jì),以區(qū)分日志和賬本存儲。除了Linux頁面緩存外,Pulsar還采用了多層緩存,即BookKeeper的bookies上的預(yù)讀緩存(測試中保留OMB默認(rèn)值dbStorage_readAheadCacheMaxSizeMb=1024),托管賬本(managedLedgerCacheSizeMB,本次測試為12GB直接可用內(nèi)存的12%為2.4GB)。測試中沒有發(fā)現(xiàn)此多層緩存有任何好處,際上,多次緩存可能會增加部署的總體成本,懷疑12GB的非堆使用情況中會有相當(dāng)大的填充,以避免前面提到的直接字節(jié)緩沖區(qū)造成Java GC問題。

RabbitMQ的性能受到了生產(chǎn)者端交換以及消費(fèi)者端這些交換綁定的隊(duì)列的影響。測試將吞吐量測試中的鏡像設(shè)置用于延遲時(shí)間測試,尤其是直接交換和鏡像隊(duì)列。由于CPU瓶頸,測試無法將吞吐量提高到高于38K消息/秒,并且以這種速率測量延遲的任何嘗試均顯示性能顯著降低,幾乎達(dá)到了2秒鐘的p99延遲。

逐漸將吞吐量從38K消息/秒降低到30K消息/秒后,就能夠獲得穩(wěn)定的吞吐量,此時(shí)系統(tǒng)似乎并未被過度利用,證實(shí)了1ms的p99延遲明顯更好??梢哉J(rèn)為在3個(gè)節(jié)點(diǎn)上復(fù)制24個(gè)隊(duì)列的開銷似乎會對更高吞吐量下的端到端延遲產(chǎn)生了巨大的負(fù)面影響,而吞吐量低于30K消息/秒或30MB/s(洋紅色實(shí)線)的RabbitMQ可以提供的端到端延遲要比其他兩個(gè)系統(tǒng)低得多。

總的來說,遵循最佳實(shí)踐可以使RabbitMQ提供有限的延遲。鑒于延遲測試是故意設(shè)置的,以便消費(fèi)者始終能夠跟上生產(chǎn)者,因此RabbitMQ消息傳遞管道的效率歸結(jié)為Erlang BEAM VM(以及CPU)處理隊(duì)列所需要做的上下文切換次數(shù)。因此,通過為每個(gè)CPU內(nèi)核分配一個(gè)隊(duì)列來限制它可以提供最低的延遲。此外,使用直接或主題交換可以將復(fù)雜的路由(類似于專門用于Kafka和Pulsar上的分區(qū)的消費(fèi)者)路由到特定隊(duì)列。但是由于沒有通配符匹配,直接交換提供了更好的性能,這增加了更多的開銷,是本次測試的合適選擇。

Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的

圖13:Kafka、Pulsar和RabbitMQ的端到端延遲,在Kafka和Pulsar上以200K消息/秒(1KB消息大?。y試,在RabbitMQ上以30K消息/秒測試。有關(guān)詳細(xì)信息,請參見原始結(jié)果(Kafka,Pulsar和RabbitMQ)。注意:延遲(ms):越低越好。

在本文的開頭,已經(jīng)介紹了Kafka使用建議的默認(rèn)全同步配置的延遲結(jié)果(綠色實(shí)線)。在Kafka將每個(gè)消息以全同步模式寫入磁盤的另一種配置中(綠點(diǎn)虛線),測試發(fā)現(xiàn)Kafka的延遲一直低于Pulsar,直到p99.9%為止,而Pulsar(藍(lán)線)在高尾百分比上表現(xiàn)更好。盡管很難在p99.9%或更高的百分比上準(zhǔn)確推斷出尾巴延遲,但可以認(rèn)為,對于替代的Kafka全同步配置(綠點(diǎn)虛線),非線性延遲會在p99.9%的百分比上急劇上升。

延遲的權(quán)衡

Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的

圖14:RabbitMQ的端到端延遲:鏡像隊(duì)列(測試中使用的配置)與傳統(tǒng)隊(duì)列(無復(fù)制)的速率為10K、20K、30K和40K消息/秒。注意:此圖表中y軸的比例為對數(shù)。

需要承認(rèn),每個(gè)系統(tǒng)在設(shè)計(jì)時(shí)都需要權(quán)衡。盡管對Kafka和Pulsar不公平,但還是發(fā)現(xiàn)在不提供高可用性時(shí)與RabbitMQ相比還是比較有趣的,RabbitMQ相對于Kafka和Pulsar而言,兩者的交易時(shí)延較低,可提供更強(qiáng)的持久性保證,并且可用性比RabbitMQ高3倍。這可能與某些場景(例如,設(shè)備位置跟蹤)相關(guān),在這些場景中,可以犧牲可用性以獲得更好的性能,這是可以接受的,尤其是在場景需要實(shí)時(shí)消息傳遞且對可用性問題不敏感的情況下。測試表明,禁用復(fù)制后,RabbitMQ可以在更高的吞吐量下保持較低的延遲,盡管改進(jìn)的吞吐量(100K消息/s)仍然顯著低于Kafka和Pulsar所能達(dá)到的水平。

即使Kafka和Pulsar速度較慢(在p99分別為~5ms~25ms),它們提供的持久性,更高的吞吐量和更高的可用性對于處理諸如金融交易這樣大規(guī)模的事件流場景,是非常重要的。對于需要較低延遲的場景,RabbitMQ僅在輕載的情況下才能實(shí)現(xiàn)p99~1ms的延遲,因?yàn)橄⒅皇窃趦?nèi)存中排隊(duì)而沒有復(fù)制開銷。

在實(shí)踐中,運(yùn)維人員需要仔細(xì)配置RabbitMQ,保持足夠低的速率以維持這些低延遲限制,從而使延遲顯著降低。任務(wù)很難,甚至實(shí)際上不可能在所有場景中以通用的方式實(shí)現(xiàn)??傮w而言,一個(gè)具有較低運(yùn)維開銷和成本的更好的架構(gòu)選擇,可能是針對所有場景選擇一個(gè)像Kafka這樣的持久化系統(tǒng),該系統(tǒng)可以在所有負(fù)載級別上以低延遲提供最佳吞吐量。

在此文中對3個(gè)消息系統(tǒng)(Kafka、RabbitMQ和Pulsar)進(jìn)行了全面、平衡的分析,得出以下結(jié)論:

吞吐量:Kafka提供了所有系統(tǒng)中最高的吞吐量,寫入速度比RabbitMQ快15倍,比Pulsar快2倍。

延遲:Kafka在較高的吞吐量下提供最低的延遲,同時(shí)還提供強(qiáng)大的持久性和高可用性。在所有延遲測試中,Kafka的默認(rèn)配置均比Pulsar更快,并且在每條消息上設(shè)置為全同步時(shí),其速度最高可達(dá)p99.9。RabbitMQ可以實(shí)現(xiàn)比Kafka更低的端到端延遲,但僅在吞吐量顯著降低的情況下。

成本/復(fù)雜度:成本往往是績效的反函數(shù)。Kafka作為具有最高穩(wěn)定吞吐量的系統(tǒng),由于其高效的設(shè)計(jì)而提供了所有系統(tǒng)中的最佳價(jià)值(即,每字節(jié)寫入的成本)。此外,從Kafka刪除ZooKeeper的工作(請參見KIP-500)正在順利進(jìn)行中,并將進(jìn)一步簡化Kafka的架構(gòu)。

關(guān)于Apache Kafka、Apache Pulsar和RabbitMQ性能測試對比是怎么進(jìn)行的就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI