本文探討了JMS消息中間件和Kafka部署的差異、權衡和架構。對于基于JMS的消息隊列 (MQ) 基礎架構和基于Apache Kafka的數據流的比較是一個廣泛的話題。本文探討JMS消息代理和Kafka部署的區別、權衡和架構,以及分析如何在JMS代理(如 IBM MQ 或 RabbitMQ)和開源Kafka或無服務器云服務(如 Confluent Cloud)之間進行選擇。
動機:蘋果與橘子之戰
Kai Waehner在Confluent擔任技術布道者,他經常在JavaOne、O'Reilly Software Architecture或ApacheCon等國際會議上發表演講,為專業期刊撰寫文章,分享新技術方面的經驗。
Kai幾乎每周都需要在客戶會議上討論JMS消息代理和Apache Kafka之間的差異和權衡。他發現時下有大量關于JMS、Kafka的誤解,偶爾也會看到一些不當的博客文章和演講,為此感到惱火,并整理了十個比較準則,目的是解釋消息隊列和數據流之間的區別,澄清相關API或實施部署的一些常見誤解,并提供相應的技術選型思考。
10個比較準則:JMS與Apache Kafka
JMS和Kafka都各自提供一系列產品和云服務, 例如:JMS API的實現(包括開源和商業產品):Apache ActiveMQ、Apache Qpid(使用 AMQP)、IBM MQ(先前是 MQSeries,現在是 WebSphere MQ)、JBoss HornetQ、Oracle AQ、RabbitMQ、TIBCO EMS、TIBCO Cloud Messaging、Solace等等。Apache Kafka產品、云服務和重寫(不僅使用開源 Kafka 的有效選項):Confluent、Cloudera、Amazon MSK、Red Hat、Redpanda、Azure Event Hubs 等。
下面是比較JMS消息代理與Apache Kafka及其相關產品/云服務的標準:1.消息代理與數據流平臺2.API規范與開源協議實現3.事務處理與負載分析4.推送與拉取消息5.簡化、強大和復雜的API6.持久存儲與真正解耦7.服務器端數據處理與解耦持續數據流處理8.復雜操作與無服務器云9.Java/JVM與任何編程語言10.單一部署與多區域(包括混合和多云)復制現在逐一探討這十個比較準則。
1、JMS與Kafka相差甚巨
JMS消息代理提供消息收發功能包括生成和使用消息。Apache Kafka是一個數據流平臺,綜合了消息傳遞、存儲、數據集成和流處理功能。
首先,在Kai看來,JMS和Apache Kafka的差別相當巨大,甚至可以說二者就不是同一個事物。
JMS API(以及IBM MQ、RabbitMQ 等的實現)JMS(Java 消息服務)是提供通用消息模型的Java應用程序編程接口 (API)。API處理生產者-消費者問題,為了方便軟件系統之間的消息發送和接收。因此,JMS消息代理(及實現JMS API)的核心功能是將消息從源應用程序實時得發送到另一個目的地程序。所以需要針對實際使用需求來選擇JMS!值得注意的一點是,項目必須使用額外的工具來完成數據集成和高級數據處理任務。Apache Kafka(開源和供應商,如 Confluent、Cloudera、Red Hat、Amazon等)Apache Kafka是一種用于數據流的開源協議實現。這包括:
- Apache Kafka是分布式消息收發和存儲的核心,具有高吞吐量、低延遲、高可用性和安全性。
- Kafka Connect是一個用于將外部源/目標連接到Kafka的集成框架。
- Kafka Streams是一個簡單的Java 庫,支持在Kafka框架內進行流式應用程序開發。
這種功能組合能夠構建端到端數據管道和應用程序,因而相比消息隊列而言,Kafka組合的用武之地要更廣。
2、 API規范與開源協議實現
JMS是供應商以他們自己的方式實施和擴展的規范。Apache Kafka是底層指定 Kafka協議的開源實現。
在評估對比JMS和Kafka之前,更重要的是澄清以下這些術語:
- 標準API:由行業聯盟或其他行業中立(通常是全球性)團體或組織指定標準 API。需要對所有功能進行合規性測試并完成認證才能符合標準。示例:OPC-UA標準
- 事實標準API:源自現有的成功解決方案(開源框架、商業產品或云服務)。示例:Amazon S3(來自單一供應商的所有權),Apache Kafka(來自充滿活力的社區的開源)。
- API規范:定義供應商如何實現相關產品的規范文檔。對于所有功能的實現,沒有完整的合規性測試或完整的認證。導致的結果是一個“標準API”,再各種實現之間沒有可移植性。例如:JMS,請注意,為了能夠使用JMS的一系列合規性組件,供應商必須向Oracle簽署非常繁瑣的報告。
替代類型的標準需要權衡取舍。如果您想了解更多信息,請查看過去幾年Apache Kafka如何成為數據流的事實標準。
與過去幾十年將工作負載放在單個數據中心相比,可移植性和遷移性在混合和多云環境中變得更加重要。
JMS是面向消息的中間件的規范
JMS是目前在Java Community Process下作為JSR 343維護的規范。最新(尚未發布)版本JMS 3.0作為 Jakarta EE 的一部分正在早期開發中,并更名為Jakarta Messaging API。今天,JMS 2.0是流行的消息代理實施中使用的規范(沒有人知道JMS 3.0將走向何方)。因此,這里重點介紹JMS 2.0規范以解決現實世界的難題。通常,當人們提及JMS時,他們指的是JMS消息代理實現,而不是JMS API規范。下文會用“JMS消息代理”來替代JMS(即 API),并沒有指定JMS實現中已知的特性。JMS消息代理和JMS可移植性神話
JMS開發規范提供一個通用Java庫來訪問不同的消息供應商的代理。它用來充當消息代理供應商專有API的包裝器,就像JDBC為數據庫API提供類似功能一樣。然而,這種簡單的集成結果并不能實現。因為將JMS代碼從一個供應商的代理遷移到另一個供應商非常復雜,原因如下:
- 并非所有JMS功能都是必需的(安全性、隊列標簽、集群、路由、壓縮等等)
- 沒有用于傳輸的JMS規范
- 沒有規范來定義如何實現持久性
- 沒有規范來定義如何實現容錯或高可用性
- 不同供應商對JMS規范的不同理解可能導致相同JMS功能具有潛在的行為差異
- 沒有安全規范
- 代理間中沒有關于增值功能的規范(例如主題到隊列橋接、代理間路由、訪問控制列表等)
因此,JMS供應商之間的簡單源代碼遷移和互操作性就是一個神話!供應商在代理中提供了大量獨特的功能(例如:主題到隊列的映射、代理路由等),它們為應用程序提供架構功能,但它們是代理功能的一部分,而不是應用程序或JMS的一部分規格。
Apache Kafka是數據流的開源協議實現
Apache Kafka是一種實時數據流處理的可靠且可擴展的實現。該項目是開源的,在Apache 2.0許可下可用,并由一個龐大的社區推動發展。Apache Kafka不是OPC-UA 之類的標準或JMS之類的規范。但是,Kafka至少提供了源代碼,參考實現、協議和API定義等。
Kafka已經成為了數據流領域的事實標準。今天,超過100000個組織使用 Apache Kafka;Kafka API也已經成為事件驅動架構和事件流的事實標準。它在所有行業和基礎設施中都有用例,包括各種事務處理和分析負載在邊緣、混合、多云環境中都有用到。
可能有些人對于Kafka API并不熟悉。這里澄清一下:如前所述,Apache Kafka是分布式數據流平臺的一種實現,包括服務器端和客戶端以及用于生產和消費事件、配置、安全性、操作等的各種API。Kafka API也是重要的,因為Kafka可重寫,如Azure Event Hubs和 Redpanda就使用了它們。
Apache Kafka的可移植性:又一個神話?
Apache Kafka作為開源項目,本身就已經是非常完整的Kafka實現。不少供應商已經使用整個Apache Kafka方案,并圍繞它構建更高級的產品。Kafka的遷移非常簡單,因為于Kafka而言,不同供應商都采用相同的規范,代碼、庫和包都是相同的。例如,從Cloudera到Confluent部署或從自我管理的Apache Kafka開源基礎架構到無服務器Confluent Cloud的遷移都非常成功。
Kafka API:Kafka的重寫Like Azure Event Hubs、Redpanda、Apache Pulsar
隨著Kafka在全球的成功,一些供應商和云服務并沒有在Apache Kafka實現上構建產品。相反,他們通過Kafka API重新構建了自己的產品。底層實現是特有的(如Azure的云服務事件中心)或開源的(如Apache Pulsar的Kafka橋或Redpanda用C++重寫的)。
所以,我們要看供應商到底是集成了整個Apache Kafka項目,還是重寫了完整的API。使用Kafka API重寫Kafka是一個全新的實現!許多供應商甚至在其支持條款和條件中,完全排除了某些組件或API(例如用于數據整合的Kafka Connect或用于流處理的 Kafka Streams),或者排除了諸如一次性語義或長期存儲等關鍵特性。
目前市面上有各種各樣的Kafka產品,比如:Confluent、Cloudera、Red Hat 或Amazon MSK等Kafka供應商,還有Azure Event Hubs、AWS Kinesis、Redpanda或Apache Pulsar等相關技術。如何評估這些呢?首先,應該對需求進行專業測試。如果Kafka-to-XYZ橋接的代碼少于一百行,或者從中間件供應商處下載的是Exe的Windows Kafka服務器程序,一定要對上述代碼和程序持懷疑態度。閃光的不都是金子。某些框架或供應商還是有華而不實的嫌疑的。比如說,僅僅支持Kafka API、提供完全托管的無服務器Kafka產品,再比如在Kafka 上強推具有不確定性和被懷疑的功能 (FUD)等。例如,Kai就對Pulsar總是試圖通過在開源社區中創建大量“不確定性和神話”來變得比Kafka更好而感到惱火。在Kai看來,“不確定性”對供應商來說都是錯誤的策略。基于這個原因,Kafka的使用率仍在瘋狂增長,而Pulsar的百分比增長要慢得多(當然,二者本身的下載量的差距也十分明顯)。
3、事務性與分析性工作負載
JMS消息代理僅支持為低容量消息提供事務功能。而Apache Kafka更為強大,它支持低容量和高容量的消息,且支持事務性和分析性工作負載。JMS:會話和兩階段提交 (XA) 事務大多數JMS消息代理都很好地支持事務性工作負載。事務處理會話支持單個事務系列。每個事務將一組產生者消息和一組消費者消息組合成一個原子工作單元。兩階段提交事務(XA 事務)在有限的范圍內工作。它們適用于與大型機CICS / DB2或Oracle數據庫等其他系統整合在一起。但操作較難,并且不能擴展到每秒幾筆交易。
需要注意的是,與會話事務不同,JMS 2.0規范并不強制支持XA事務。
Kafka:Exactly-Once Semantics和事務API
Kafka是一個分布式的容錯系統,天生具有彈性(如果您正確部署和操作它)??梢源_保沒有宕機和數據丟失,就像在您最喜歡的數據庫、大型機或其他核心平臺中一樣安全可靠。
甚至更好:Kafka的事務API,即Exactly-Once Semantics (EOS),從Kafka 0.11開始可用。EOS使構建事務工作負載變得更加容易,因為您不再需要處理重復項。Kafka通過事務API支持跨多個分區的原子寫入事務。這允許生產者將一批消息發送到多個分區。批處理中的所有消息最終對任何消費者都是可見的,或者對消費者不可見。
Kafka事務的工作方式與JMS事務非常不同。但目標是相同的:每個消費者只接收一次生成的事件??梢栽诓┛臀恼隆笆褂肁pache Kafka的數據流中的分析與事務”中查找更多詳細信息。
4、Push vs. Pull 消息消費
JMS消息代理將消息推送到消費者應用程序。Kafka消費者拉取消息,為獨立的消費者應用程序提供真正的解耦和背壓處理。
對于像基于JMS的消息代理這樣的實時消息系統來說,推送消息似乎是顯而易見的選擇。但是,基于推送的消息傳遞在解耦和可擴展性方面存在各種缺點。
JMS希望代理提供背壓并實現“預取”功能,但這不是強制性的。如果使用,代理將控制您無法控制的背壓。
使用Kafka,消費者可以控制背壓。每個Kafka消費者實時、批量或僅按需消費事件——以特定消費者支持和處理數據流的方式。對于許多不靈活和非彈性的環境來說,這是一個巨大的優勢。
因此,雖然JMS有某種背壓,但如果隊列已滿,生產者就會停止。在Kafka中,您可以控制消費者的背壓。無法使用JMS擴展生產者(因為JMS隊列或主題中沒有分區)。
JMS消費者可以擴展,但會失去有保證的排序。JMS消息代理中的保證排序僅通過單個生產者、單個消費者和事務起作用。
5、二者的API復雜度不同
JMS API提供了簡單的操作來生成和消耗消息。Apache Kafka有一個更細粒度的API,它帶來了額外的功能和復雜性。
JMS供應商在規范下的實現中隱藏了所有很酷的功能。你只得到5%(無控制,由供應商提供的功能)。你需要自己實現剩下的功能。相反,Kafka暴露了一切功能,而大多數開發人員只需要5%。總之,請注意JMS消息代理的構建是為了將消息從數據源發送到一個或多個數據接收器。Kafka是一個數據流平臺,提供更多功能、特性、事件模式和處理選項;并且平臺規模更大。考慮到這一點,二者的API非常不同并且具有不同的復雜性也就不足為奇了。如果您的用例只需要每秒從A向B發送幾條消息,那么JMS是正確的選擇并且使用簡單!如果您需要任意規模的流數據中心,包括數據整合和數據處理,那只有Kafka。
異步請求-回復與動態數據JMS開發人員的一個初衷是使用Kafka中的請求-響應功能。請注意,這種設計模式在消息傳遞系統中與RPC(遠程過程調用)不同,消息代理中的請求-回復是一種利用相關ID的異步通信。
從生產者(比如移動應用程序)到消費者(比如數據庫)獲取事件的異步消息傳遞是一種非常傳統的工作流程。無論是執行發后即忘還是請求回復,數據都將置于靜止狀態以供進一步處理。JMS支持開箱即用的請求-回復,非常簡單。Kafka日志是持久的,帶有事件流的動態數據會持續處理數據。Kafka應用程序實時或批量維護和查詢狀態。對于大多數開發人員和架構師來說,數據流是一種范式轉變。這種設計模式非常不同。千萬不要嘗試使用相同的模式和API在Kafka中重新實現JMS應用程序。這種反模式極可能失敗。
請求-響應模式的效率低下可能會導致非常多的延遲,而HTTP或gRPC適用于某些特定的用例。CQRS(命令查詢職責隔離)將“請求-響應”替換為流數據的Kafka。但JMS API則無法實現CQRS,因為JMS不提供狀態功能并且缺乏事件溯源功能。請求-響應模式的Kafka示例對于許多Kafka用例,CQRS是更好的設計模式。盡管如此,請求-響應模式也可以用Kafka來實現,但注意:嘗試像在JMS消息代理中那樣做(帶有臨時隊列等)最終會宕機Kafka集群(因為它的工作方式不同)。Kafka Spring Boot Kafka模板庫有大量的實例,其使用Kafka構建的請求-回復模式。
Kafka模板的Spring文檔有很多關于Kafka的請求/回復模式的詳細信息。因此,如果使用Spring,那么使用Kafka實現請求/響應模式非常簡單。
6、持久性存儲與真正的解耦
JMS消息代理使用存儲系統來提供高可用性。Kafka的存儲系統更先進,可以實現歷史事件的長期存儲、背壓處理和可重放功能。
Kafka存儲遠不止JMS的持久性功能
當Kai向經驗豐富的JMS開發人員解釋Kafka存儲系統時,幾乎總是得到相同的回應:“我們的JMS消息代理XYZ也有存儲。Kafka的好處在哪里?”JMS使用臨時存儲系統,其中消息僅在被處理之前被持久化。
消息的長期存儲和可重放性功能就不是為JMS設計的概念
附加日志、偏移量、排序保證、保留時間、壓縮主題等Kafka的核心原則提供了許多超出JMS的持久性保證的額外好處。背壓處理、消費者之間的真正解耦、歷史事件的可重放性等等是JMS和Kafka之間的巨大差異。翻閱Kafka文檔,深入了解Kafka存儲系統。Kafka的分層存儲,通過在Kafka日志中提供更好的可擴展性和具有成本效益的長期存儲,也是值得深究的技術細節。
7、數據處理方式不同
JMS消息代理提供簡單的服務器端事件處理,例如基于消息內容的過濾或路由。Kafak消息代理是不夠智能的。它的數據處理在解耦的應用程序/微服務中執行。
JMS服務器端過濾和路由
大多數JMS消息代理都為服務器端事件處理提供了一些功能。這些功能對于某些工作負載很方便!請注意,服務器端處理通常是有代價的。例如:
- JMS預過濾可伸縮性問題:代理必須處理很多事情。這可以用隱藏的方式宕掉JMS服務。
- JMS選擇器(路由)性能問題:它會消耗掉集群40-50% 的性能
當然,如果可以容忍這些缺點,那么它也不失為一個很棒的功能。
Kafka:弱管道和強終端
Kafka 有意不提供服務器端處理,這處理發生在智能端點。這是一個非常著名的設計模式:弱管道和強終端
缺點是您需要分別在應用程序/微服務/數據產品中實現相關邏輯。這在無服務器環境中不是大問題。它在自我管理的環境中變得更加復雜。
然而,這種架構一個非常大的好處在于:應用程序/技術/編程語言之間可以做到真正解耦,用于構建業務邏輯和基礎設施操作的業務單元之間的關注點分離,以及更好的可擴展性和彈性。
Kafka未來是否會有一定的服務器端處理能力?Kai認為當然會有。特別是對于少量工作負載,性能和可擴展性的影響都應該是可以接受的!不過,風險在于開發者是否會濫用這些功能。未來將會證明Kafka是否具有此項功能。
復雜操作與無服務器云
可擴展JMS消息代理或Kafka集群的自我管理操作很復雜。無服務器產品(應該)擔負起運營重擔。
不管是JMS還是Kafka,操作集群都很復雜
一個基本的JMS消息代理相對容易操作(包括主動/被動設置)。但是,這限制了可擴展性和可用性。JMS API旨在與單個代理或主動/被動通信以實現高可用性。這個概念涵蓋了應用領域。對于 JMS 消息代理來說操作集群是非常復雜。來自商業供應商的更高級的消息代理集群更強大,但是也更難操作。Kafka是一個強大的分布式系統。
完全托管的無服務器云救援
在Kafka中,這情況就不同了。由于Kafka是一個可擴展的分布式系統,云提供商可以構建云原生無服務器產品。構建這樣一個完全托管的基礎設施仍然非常困難。因此,評估相關云產品,而不僅僅是看其外在的營銷口號!
每個Kafka云服務都標榜為“完全托管”或“無服務器”,但大多數不是。一些云供應商甚至從他們的Kafka云產品中排除了對Kafka的支持。瘋狂,但夠真實。所以檢查條款和相關條件可以作為評估的一部分。
9、Java/JVM 與任何編程語言
JMS專注于JVM編程語言的Java生態系統。而Kafka獨立于編程語言。
正如名稱JMS(及Java 消息服務)所說:JMS是專門為Java編寫的。一些代理供應商支持他們自己的API 和客戶端。這些是該供應商專有的。我過去見過的幾乎所有重要的JMS項目都使用Java代碼。
Apache Kafka也只提供了一個Java客戶端。但是供應商和社區為幾乎所有編程語言提供了其他語言綁定,以及用于HTTP通信的REST API,用于生成/消費來自Kafka的事件。
Kafka后端的真正解耦使不同的客戶端應用程序能夠相互交流,無論使用哪種編程語言。這種靈活性允許構建適當的領域驅動設計 (DDD),其中微服務架構利用Kafka作為中樞神經系統。
10、單 JMS 部署與多區域(包括混合云和多云)Kafka 復制
JMS API是應用程序和代理之間通信的客戶端規范。Kafka是一個分布式系統,可為混合云和多云用例提供各種架構。
JMS是客戶端規范,而多數據中心復制是代理功能。這里不再深入講解,簡單地說:JMS消息代理不是為跨區域、洲際或混合/多云環境的復制場景而構建的。
Apache Kafka的多集群和跨數據中心部署已成為常態而非例外。各種場景需要多集群Kafka解決方案。可以根據實際情況進行考慮具體要求和權衡取舍。諸如MirrorMaker(開源)或Confluent Cluster Linking(商業)等Kafka技術都支持災難恢復、聚合分析、云遷移、任務關鍵延伸部署和全域Kafka部署等用例。
11、JMS 和 Kafka對比總結
以上這10個比較維度,表明JMS和Kafka是有著非常大差異的。雖然兩者也有重疊的領域(例如,消息傳遞、實時、關鍵任務),但它們使用不同的技術能力、特性和架構來支持其他功能用例。
簡而言之,使用JMS代理進行從A到B的簡單和低容量的消息傳遞。而Kafka通常是許多數據源和數據接收器之間的實時數據中心(許多人稱其為企業架構的中心實時組織系統)。
Kafka在任意規模的數據集成和數據處理能力、真正的解耦、事件可重放性是與基于JMS的MQ系統的主要區別。但是,尤其是在無服務器云中,不要擔心Kafka太強大(太復雜)。無服務器Kafka項目通常以非常低的容量、非常便宜的方式進行,沒有運營負擔。然后它可以隨著您不斷增長的業務而擴展,而無需重新構建應用程序。
12、選擇與評估要考慮哪些?
了解基于JMS的消息代理和由Apache Kafka提供支持的數據流之間的技術差異。評估這兩個選項以找到解決問題的正確工具。在消息傳遞或數據流中,進行更詳細的評估。每個消息代理都是不同的,即使它們都符合JMS。同樣,所有Kafka產品和云服務在功能、支持和成本方面都不同。
所以開發者應針對實際需求和二者的用例及限制來進行適當的選擇。
?譯者介紹
田小保,51CTO社區編輯,資深云計算架構師,互聯網老兵,擁有15年以上互聯網軟件開發和架構經驗,具有多年的項目管理經驗。熟悉云計算、大數據等的互聯網開發技術。
原文鏈接:
https://dzone.com/articles/comparison-jms-message-queue-vs-apache-kafka?fromrel=true