Cloud Pub/Sub 教學:比 RabbitMQ 好用,無限擴充的訊息佇列服務

Cloud Pub/Sub (簡稱 Pub/Sub) 是一個全代管的即時訊息服務,主要用於應用程式之間的非同步通訊。它採用發布-訂閱(Publisher-Subscriber)的架構模式,讓資料產生者和使用者能夠獨立運作,大幅提升系統的彈性和可擴充性。

為什麼我們需要 Cloud Pub/Sub?

在現代的分散式系統中,不同的服務組件往往會面臨以下挑戰:

後端處理速度跟不上

當前端產生資料的速度遠大於後端處理的速度時,系統就會出現瓶頸。例如,電商網站在促銷活動期間,訂單產生的速度可能遠超過庫存系統的處理能力。

又或是遊戲架構,通常會有高低峰期,像白天線上可能只有 100 多人,但是晚上可能高達 10,000 人在玩遊戲,可是你後端只有一台機器,會來不及處理持續不斷送進來的資料,影響到使用者體驗。

流量衝擊與系統穩定性

資料處理來不及是一回事,請求突然暴增,直接衝擊到後端系統,很容易造成服務過載甚至當機,最好要有一個緩衝機制,先讓資料在某個地方「排隊」,不要直接「打進」後端,確保系統穩定。

系統耦合度過高

當系統元件之間過度依賴時,任何一點故障都可能影響整個系統的運作。Pub/Sub 扮演了一個「智慧排隊系統」的角色,讓訊息能夠讓各個服務單獨處理,不會因為某個服務壞掉,大家都不能再處理訊息。

如果串流資料量太大,後端承受不住的後果

MQTT 協定的演進與 Pub/Sub 的關係

在了 Pub/Sub 之前,早期有個協定叫做 MQTT(Message Queuing Telemetry Transport)。MQTT 最初由 IBM 在 1999 年開發,目的是為了在衛星網路中傳輸石油管線的感測器資料。目前也廣泛應用在物聯網的應用,例如收集各種感測器回傳的資料,或是從工產的生產線收集設備或產品資料,確保生產線沒有異常。

MQTT 採用發布-訂閱模式,在架構中,有三個核心角色:

發布者(Publisher):負責發送訊息到特定主題

訂閱者(Subscriber):或叫客戶端 (Client) 訂閱感興趣的主題並接收訊息

訊息代理(Message Broker):居中協調,負責接收、儲存和轉發訊息

MQTT 架構

這種模式的優點是發布者和訂閱者之間完全解耦,彼此不需要知道對方的存在,也不需要同時在線上。這種設計理念深深影響了後來許多訊息系統的架構,當然也包括 Pub/Sub。

Cloud Pub/Sub 的核心概念

Google Cloud Pub/Sub 沿用了 MQTT 的發布-訂閱概念,但針對雲端環境進行了大幅優化:

主題(Topic):

就像是一個訊息的分類標籤,發布者將訊息發送到特定主題中。例如,電商網站可能會有「user-clicks」、「purchase-events」等不同主題。

訂閱(Subscription):

代表對某個主題的訂閱關係。一個主題可以有多個訂閱,每個訂閱都會收到該主題的所有訊息副本,這讓同一份資料可以被多個不同的服務同時處理。

訊息(Message):

實際傳遞的資料內容,可以是 JSON、二進位資料或任何格式,每個訊息都有唯一的 ID 和時間戳記。

如下架構圖,Pub/Sub 的訊息傳送還可以分成 Pull 和 Push 兩種,Pull 是 Subscriber (或叫 Consumer) 主動去 Subscription 拉取訊息,如果要確保 Subscriber 能夠確實處理到每一筆訊息,適合使用 Pull 方式。如果希望訊息即時傳送出去,則建議使用 Push 方式。

Pub/Sub 架構

Cloud Pub/Sub 的技術優勢

相較於傳統的訊息佇列系統,Pub/Sub 提供了幾個重要特性:

擴展性高

能夠處理每秒數百萬筆訊息,並且自動根據負載進行擴充,這種分散式的處理架構,遠遠超過傳統只能用一台機器處理的能力。

至少一次傳遞保證 (Exactly-Once Delivery)

確保每個訊息至少會被傳送一次,避免資料遺失。同時提供訊息確認機制,只有當訂閱者確認處理完成後,訊息才會從佇列中移除。

順序保證

透過訊息排序功能,可以確保相關訊息按照正確順序處理,這對金融交易相關應用特別重要。

無效信件處理 (死信佇列 Dead Letter Queue)

發送失敗的訊息暫存區 (Subscription),訊息在此不會再持續發送,由後端主動來收訊息 (Pull 模式)。

死信佇列 Dead Letter Queue 架構

Pub/Sub 基本操作示範

建立 Pub/Sub Topic

接下來我們可以快速體驗一下 Pub/Sub 如何運作,我們先建立一個主題為叫 my-topic。

順便勾選「新增預設訂閱項目」:

建立 Pub/Sub Topic

從 Cloud Shell 發送串流訊息

然後打開 Cloud Shell,執行以下指令碼,它會每 10 秒鐘發出一個 Hello 訊息,加上發出訊息當下的時間:

while true; do   gcloud pubsub topics publish my-topic --message="Hello! 時間:$(date '+%Y年%m月%d日 %H時%M分%S秒')";   sleep 10; done
使用 Cloud Shell 發送串流訊息

接收 Pub/Sub 訊息

我們去訂閱項目 my-topic-sub 的「訊息」,按下「提取」:

接收 Pub/Sub 訊息

接下來等幾秒鐘,就會馬上看到收到的訊息,非常快。

確認 Pub/Sub 訊息

而這些訊息是還沒有被確認的狀態,而且在「確認」欄位顯示為「已超過確認期限」,因為預設的確認截止時間是 10 秒 (可以延長),我的手速太慢,擷圖的時候已經超過時間了。

那我們就勾選「啟用確認訊息」,再按一次「提取」,它就會把最舊的兩筆訊息顯示一個「確認」按鈕,因為 Pub/Sub 重新傳送未確認的訊息,所以確認截止時間會重新計算,現在又可以按「確認」了。

這就是所謂的「At-least-once delivery」:確保訊息至少被傳遞一次。而且會持續重試,直到被確認為止,不然就是到了 7 天之後,訊息過期。

我們再按下「確認」的話,訊息才會被刪除,它們就不會再出現在訂閱項目中了。

你會發現這些訊息一直改變它的狀態,本來可以按確認的訊息,又會一個一個到期,你就直接再「提取」,它們又會不斷出確認按鈕,有點像在打遊戲的感覺!

確認 Pub/Sub 訊息

停止發送訊息

最後記得在 Cloud Shell 那邊,按下 ctrl + C 喔,不然訊息會一直累積下去,你就確認不完喔!

前面提到的 Pub/Sub,只是讓傳過來的資料先暫時排隊起來,我們再用後端服務來消化資料。

但是如果資料多到「怎麼樣都處理不完」的話,就不得不介紹 Cloud Dataflow 這個服務,有需要可以參考《Dataflow 是什麼?跟 Apache Beam 有什麼關係?》這篇文章喔!

Table of Contents
返回頂端