技術專欄

集結國內外精選文章,掌握最新雲端技術新知與應用 

iKala Cloud / 部落格 / 資料管理與分析 / 拆解雲端 Message Service:Google Cloud Pub/Sub vs. AWS SQS 優劣分析

拆解雲端 Message Service:Google Cloud Pub/Sub vs. AWS SQS 優劣分析

最近有機會在 GCP 上開發分散式的系統,透過 GCP Cloud Pub/Sub 來解決我們系統上的瓶頸,於是整理了有關 Pub/Sub 的使用心得與經驗,同時與過去使用 Amazon Simple Queue Service (SQS) 比較。

Cloud Pub/Sub 簡介

在 Pub/Sub 中有下列角色:

•  Pub/Sub topic: Publish application 可以創建 topic 用來發送 messages (tasks) 到此 topic。
•  Pub/Sub subscription: Subscriber applications 可以建立多個 subscription 訂閱同一個 topic,當此 topic 有新的 messages 時,會同時發送到所訂閱的 subscription。
•  Publisher application: 發送 messages 到特定的 Pub/Sub topic。
•  Subscriber application: 從特定的 Pub/Sub subscription 接收 messages、處理。

與 AWS SQS 較大的不同是,在 Pub/Sub 中,可以支援出 one-to-many (fan-out), many-to-one (fan-in), many-to-many 的系統架構。

Pub/Sub 主要處理的流程如下:

1. Publisher application 在 Pub/Sub 中創建一個 topic,然後可以將 messages 傳送至這個 topic 中。
2. 被傳送至 topic 中的 message,在被處理 (收到 subscriber 的 acknowledge request) 前,會被保存在這個 topic 中 (預設為保留七天,七天之後如果 Pub/Sub 都沒有收到 acknowledge request 的話,Pub/Sub 會自動刪除這筆 message)。
3. Subscriber applications 向 Pub/Sub 訂閱 subscription 後,所有被發送到 topic 的 messages 都會發送到 定閱的 subscriptions,這時候 subscriber applications 可以有兩個動作:
4. 主動向 Pub/Sub 發送 pull 請求,拿到 messages。
5. 設定 public endpoint 讓 Pub/Sub 推送給你的 subscribers。
6. Subscriber applications 在處理完 message 後,會依照 message id (每個 message 都有的 unique id),發送 acknowledge request 給 Pub/Sub,以確定訊息已經處理完成。
7. 當 Pub/Sub 收到某一 message id 的 acknowledge request 後,會將此 message 從 Pub/Sub 中刪除。

Cloud Pub/Sub 主要處理流程 在 fan-out 架構中,多個不同的 device 可以做為 publisher application 將所蒐集到的資料丟到同一個 topic,再透過多個 subscriptions fan-out 到多個 subscribers。
 Cloud Pub/Sub 架構
在 AWS SQS 中,並沒有支援 fan-out 的功能,想要實作類似的架構,需要透過 Amazon Simple Notification Service (SNS)Amazon Simple Queue Service (SQS)整合才行:

GCP Pub/Sub 的優勢

優勢一

天生就可以實作 many-to-many 架構,透過 Pub/Sub 作為中間橋接的角色,使用者只需要專注在不同 subscriber 的開發。

優勢二

Pub/Sub 支援 push 和 pull 兩種 subscription (AWS SQS 中只支援 pull)

 在 push subscription 中,你需要在 Pub/Sub 的設定中,填入一個 public IP 或是一個讓外界可以存取得到的 endpoint。

在 push subscription 是被動等待訊息推送過來,因此在 subscriber 必須實作一個 HTTP Server 等待 Pub/Sub 推送訊息。當 Pub/Sub 一收到訊息會立即推送到 endpoint,適合即時性高的服務。

Pull subscription 顧名思義就是 subscriber 定期向 Pub/Sub pull message 進行處理。而在 Google 所提供的 Node.js SDK 中,又有兩種 pull 的方法:

Asynchronous Pull

 

對開發者來說,只要去透過 Node.js 監聽 Pub/Sub 的 event 就好,當有新的 message 進到 subscription 時,會觸發 message event 的 callback。但是請記得處理完拉到的 message 後要針對這筆 message 發送 acknowledge request,不然 subscriber 會一直處理到相同的 message。

Pull

透過 subscriber 主動到 Pub/Sub 抓取 message 下來處理。此方法的優點是速度可以由 subscriber 控制,做完手上的任務後再抓取新的 message。不會對 subscriber 造成太大的效能問題。

 

AWS SQS 的優勢

我覺得 AWS SQS 最大的優勢有兩個:

優勢一

支援 dead letter queue。可以在設定當一個 message 被 subscriber re-try 幾次之後,就自動 forward 到 dead letter queue 中。

這樣的好處在於,如果有一筆 message 是有問題的 (例如資料格式錯誤或是不在存時),在 subscriber re-try 幾次之後,AWS SQS 會自動將這筆 message forward 到你指定的 dead letter queue 中。而不會繼續留在原本的 queue 中佔用 subscriber 的資源。

優勢二

在某些 region 已經有 first-in/first-out 的 queue 了,可以針對你系統的需求使用。

使用 GCP Pub/Sub 要注意

一開始在使用 Pub/Sub 時,每天都在懷疑人生 XD,因為不管再怎麼調整都達不成我們一開始設定的容量目標,心想到底是 Google 服務有問題,還是我們不會使用 XD

1. 為什麼 scale out 了 subscriber,Pub/Sub 的 query per second (qps) 還是這麼低? 會造成這個現象,可能會有幾個原因:

•  如果你是使用 pull 的話,是否 subscriber 處理每個 message 的時間太久了,特別是在處理任務時,需要用到網路、I/O 等資源。當處理 message 的時間變長了,就會影響到 subscriber pull message 的次數,進而造成 qps 低落。

•  是否你在同一個小資源的平台上(例如一台 VM 上)跑了多個 subscriber,進而讓 VM 上的資源限制住 subscriber 的處理速度。

2. Acknowledge deadline 的重要性

•  在設定 acknowledge deadline 時,請設定一個 「合理」、「安全」 的時間。因為只要當 acknowledge deadline 時間一到,你還沒有針對此筆 message 發送 acknowledge request 的話,這筆 message 就會重新回到 Pub/Sub 中,讓下一個 subscriber 拿取,會造成 message 被重覆(duplicate) 做了多次。
•  一般會估算處理 message 的最大處理時間,例如為 1 分鐘,而保險的做法就是將 acknowledge deadline 設為比處理時間長的時間,例如: 2–3 分鐘。
•  Pub/Sub 同時也提供 modify ack deadline 的 API,可以在 deadline 快到時延長時間。

3. 目前在 Pub/Sub 中不保證訊息的順序性

4. Message 可能會發生重覆(duplicate),有兩種處理方式

•  Message 不能重覆執行,就需要在 message 夾帶的 unique id 在執行的時候進行確認,如果已經執行過,就 by pass,並且發送 acknowledge request 將它從 Pub/Sub 中移除。確認的方式可以透過像是將 uuid 存在 Redis 這種 thread safe 的 DB 中,以確保不同的 subscriber 不會互相做到相同的 message。
•  Message 可以重覆執行,程式便能忽略重覆性確認的流程。但是需要注意的是 「重複執行了幾次」 需要 subscriber 計算,如果真的重做了很多次 (例如 100 次) 則需要對此 message 做特別的處理,例如將此 message 刪除並搬到另一個 topic 或是直接刪除,以減少系統資源的浪費。

結論

在使用兩台大平的 queue service 之前,我們也有透過 self-hosting 開發自己的 queue,例如:beanstalkdApache Kafka,但往往專案上線後,都會發現現 self-hosting 的服務難以維運 (畢竟我們不是像 LinkedIn 等等的大公司,無法投入許多人力資源研究) 或是發生效能的問題不好找到解決的方法。

建議在考慮類似解決方案時,可以多利用 cloud service,好處是可以不用管理機器減少維運的成本、避免再造輪子,當真的發生無法解決的問題時,還可以發 support ticket 取得原廠的支援。

Reference

•  https://cloud.google.com/pubsub/docs/overview
•  https://cloud.google.com/docs/compare/aws/application-services
•  https://aws.amazon.com/tw/sqs/details/
•  https://www.schibsted.pl/blog/choosing-best-aws-messaging-service/
•  https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-configure-dead-letter-queue.html
•  https://tachingchen.com/tw/blog/google-cloud-pubsub-introduction/
•  https://cloud.google.com/pubsub/docs/subscriber#pull-subscription
•  https://cloud.google.com/nodejs/docs/reference/pubsub/0.18.x/v1.SubscriberClient#modifyAckDeadline

(本文來自合作部落客 Levi Chen:Always Improve Yourself,GCP 專門家授權轉載。)

 

閱讀更多:

 

分享本文:
FacebookLineTwitter
回到頂端