如何為微服務選擇正確的消息隊列

微服務及消息隊列簡史

自從 Peter Rodgers 博士 2005 年在 Web Services Edge 會議上首次提出 Micro-Web-Services 一詞後,IT 行業慢慢地從單體架構轉向了微服務。

2009 年,Netflix 決定把其單體架構拆分為微服務。

2010 年,Best Buy 開始把它們的單體架構轉變為微服務架構。

2011 年,eBay 開始推行微服務。

2001 年,當時 Amazon 的零售網站還是個巨大的單體架構。

Rob Brigham 在 Amazon 的 re:Invent 2015 會議上提出了微服務改造建議:

 

  • 將服務端拆分成松耦合的微服務

  • 隔離微服務時應該關注業務而非團隊技術棧

  • 成立更小單位的研發團隊,專註於定義良好的服務,使他們可以更高效、更大規模的完成交付

 

今天,服務端基本都遵循微服務架構設計模式。然而,基於消息隊列的進程間或執行緒間通訊可以追溯到 20 世紀 80 年代初,當時使用的是 UNIX 的 V API 或其它實時作業系統內核。直到 2000 年代,基於網路間通訊的消息隊列才誕生。

 

  • RabbitMQ 在 2007.07.01 發布了它的 v1.0.0 版本

  • Kafka 最初由 LinkedIn 開發,隨後於 2011 年初開源

  • Amazon SQS 於 2004 年底進入測試階段,並於 2006 年年中正式上市

 

使用同步通訊還是非同步通訊

選擇了微服務架構,就面臨著選擇服務間的通訊協議:

 

  • 同步:HTTP,如 REST、SOAP、RPC、gRPC 等

  • 非同步:消息隊列,如 AMQP、Kafka、MQTT 等

 

同步通訊更容易出錯,更難調試,也更難恢復。如果不是實時性要求特彆強的功能,可以考慮非同步通訊。

非同步通訊提供了單一、可靠的消息匯流排,使得調試更容易,更不容易出錯,服務間數據傳遞更可靠也更安全。

也就是說,除非存在使用較舊程式語言的遺留服務,或者無法改造的舊基礎架構,雲原生時代更建議選擇非同步通訊。

選擇了使用非同步方法,就需要決定使用什麼消息隊列中間件和消息隊列協議。

 

消息隊列中間件

以下是截至 2021 年比較著名的消息隊列中間件以及雲服務列表:

  • RabbitMQ

  • Apache Qpid

  • Apache Kafka

  • Apache ActiveMQ

  • Redis

  • Eclipse OpenMQ

  • JoramMQ

  • Eclipse Mosquitto

  • HiveMQ

  • Solace PubSub+

  • Google Cloud Pub/Sub

  • Amazon SQS

  • Amazon MQ

  • IBM MQ

  • Azure Event Hubs

  • Azure Service Bus

 

消息隊列協議矩陣

以下是消息隊列協議比較矩陣:

注意:Headers 表示具有任意數量鍵的 dictionary 或 map,而 attrs 表示一組有限的鍵值對。

 

相似點:

  • 所有協議都有隊列的 FIFO 概念

  • 所有協議都基於 TCP

  • 所有協議都有生產者、消費者的概念

  • 所有協議都有負載(payload)與正文(body)

 

不同點:

  • AMQP 有不同的消息傳遞模型

  • Cloud-based 的消息隊列具有死信隊列

  • 消息檢索(routing key)方法不同

  • Headers 和 attrs 的支援有限

  • Redis、STOMP、MQTT 的功能最不豐富,而 AMQP 的功能最豐富

  • Cloud-based 的消息隊列具有一些獨特的配置以及相關 API。

 

消息隊列協議詳解

消息隊列協議的選擇實際上比消息隊列中間件的選擇更重要。因為如果選擇一個更通用的協議,就更容易找到其他中間件作為替代。

 

AMQP

AMQP – Advanced Message Queue Protocol 是一種基於 TCP 的二進位協議,已成為 ISO 和 OASIS 的標準,AMQP 協議主要由 RabbitMQ 使用。

 

優點:

  • 針對不同的用戶場景使用不同的消息傳遞模型,在協議級別降低了架構的複雜性

  • AMQP 是 ISO 和 OASIS 標準,被廣泛採用

  • AMQP 快速、安全,可能是消息隊列協議中最成熟的

  • 可以在公有雲上找到對應的雲產品,並且可以在雲產品和自有 RabbitMQ 間輕鬆切換

  • 使用 classical 隊列或 quorum 隊列進行隊列鏡像,使其易於擴展

  • RabbitMQ 的消息大小限制在版本 3.7.0 之前為 2GB,在版本 3.8.0 中減少到 128MB

 

缺點:

  • 不向下兼容,客戶端只實現協議的一個版本,版本之間升級遷移可能很耗時

  • 依賴 RabbitMQ 許多插件可能會面臨運維挑戰

  • 調試和監控可能存在問題

  • 雖然 AMQP 感覺像是標準化的消息隊列協議,但大多數消息隊列中間件都不支援它

 

Apache Kafka

Apche Kafka 既是消息隊列中間件的名稱,也是協議本身。截至 2021,該協議共有 12 個版本,客戶端可同時兼容所有版本。

Apche Kafka 是一個由 Apache 軟體基金會開發和維護的項目,用 Scala 和 Java 編寫。

Apache Kafka 團隊選擇定義自己的協議,而不是採用 AMQP 或 STOMP。是因為他們認為協議決定了實現,因此,採用已有的協議會降低了他們創建分散式消息中間件以及進行某些優化的自由度。

 

優點:

  • Apache Kafka 的 partition 和 replication 的功能使其易於擴展

  • Apache Kafka 提供了一種批量發送小消息的方法,使得該協議非常高效

  • Apache Kafka 提供的管理 API 使調試變得很容易

 

缺點:

  • Apache Kafka 需要部署 ZooKeeper 和 Kafka 兩部分,對於初學者而言具有一定的挑戰性

  • Apache Kafka 協議規範不斷升級變化,客戶端可能很難跟上其變化,升級也可能具有挑戰性

  • 消息大小限制為 1MB

 

STOMP

STOMP – Streaming Text Oriented Messaging Protocol 是一種基於文本的協議,與 AMQP 非常相似。但它缺乏其他協議所具有的許多功能和優化。另一方面,STOMP 的簡單性使其更易於採用。因此,有許多客戶端支援該協議,RabbitMQ 也可以通過插件支援 STOMP。對於一些簡單的用例或快速原型,可以考慮使用 STOMP。

 

優點:

  • 簡單,易於集成

  • 通過插件方式支援 RabbitMQ

 

缺點:

  • 與其他協議相比,功能和優化更少

 

MQTT

MQTT – Message Queuing Telemetry Transport 是物聯網(IoT)的消息隊列協議,它是 ISO 和 OASIS 標準,當前支援 MQTT 的最著名的中間件是 Eclipse Mosquitto 和 HiveMQ。

 

優點:

  • 輕量

  • 雙向

 

缺點:

  • 不適用於與物聯網無關的微服務

  • 功能不夠豐富

 

Redis

RESP – Redis Serialization Protocol 是 Redis 的協議。Redis 是一個基於記憶體的 Key-Value 資料庫。從技術上講,Redis 不是一個消息隊列中間件,但通過一些客戶端手段,Redis 可以用於非同步消息通訊。這主要是那些喜歡使用 Redis 的開發者或者一些簡單場景採用的手段,因此,也把 Redis 納入消息中間件。

 

優點:

  • Redis 基於記憶體,速度相當快

  • 對於已經使用 Redis 的人來說,基本無學習曲線

 

缺點:

  • 消息沒有持久化,有丟消息的風險
  • 功能不夠豐富
  • 不適用於其他協議能解決的所有應用場景

 

雲服務,如 AWS SQS

如果不想自己維護基礎設施,並需要自動擴容,或者本身就在公有雲上,此時,可以考慮直接使用雲服務。

 

優點:

  • 方便快捷

  • 穩定,自動擴容

  • 無需個人維護

 

缺點:

  • 對於簡單或輕量的業務場景 ,費用可能過高

  • 客戶端兼容問題依賴雲廠商解決,對某些開發語言可能兼容不好

  • 非客戶端交互模式,如 API 方式可能存在性能問題

 

如何選擇消息隊列

總之,一般情況下使用 AMQP – RabbitMQ 或 Kafka,對消息可靠性要求較高時考慮 RabbitMQ,否則選擇 Kafka。

請勿採用 STOMP,因為它沒有被很好的兼容,而且沒有很好的優化。

如果您在從事物聯網業務,那麼請使用 MQTT,它適合物聯網。

如果您喜歡 Redis,並且無法添加其它新技術,那麼可以繼續使用 Redis,但需要接受 Redis 在消息隊列中的缺點。

如果您本身就在使用公有雲,具備一定的用戶或業務體量,對消息隊列有穩定性及自動擴容的要求,並且能接受其費用,那麼,選擇雲服務提供的消息隊列。

 

參考總結

以上就是本文希望分享的內容,如果大家有什麼問題,歡迎在文章或者公眾號 – 跬步之巔留言交流。