極光筆記 | 聊一聊推送系統中事件驅動架構的應用

微服務間通信方式主要有2種:RPC和消息傳遞。

通常來說在請求/響應的場景下使用RPC更加合適,具體實現通常是REST API或者基於長鏈接的協議(例如gRPC/Thrift/Zero ICE等)。兩個服務有比較強的依賴關係, 調用者依賴被調用者的處理結果,調用者處理該請求被堵塞以等待響應結果,同時還要進行負載均衡、限流、熔斷、錯誤處理等。通常是同步的、一對一的交互,異步RPC本質也是要等待響應結果才能繼續處理該請求。

消息傳遞以異步消息作爲載體,通過事件代理(消息中間件)連接消息處理的上游和下游,上游和下游鬆散耦合,通常上游的處理邏輯不依賴下游的處理結果,具體實現通常有發佈者/訂閱者和事件流等。而事件驅動架構(EDA)就是基於消息傳遞,通過解耦生成、傳輸和處理事件,協調事件生產者、消息中間件、消費者工作的一種架構模式,具有鬆散耦合、流量削峯、非阻塞、易於擴展、更高的彈性和錯誤處理能力等優點。不過也帶來性能損耗、複雜性等方面的問題。

推送系統的業務形態
在推送系統中,一個推送請求的處理流程大致如下:

  1. 接收請求,進行用戶身份認證、參數校驗、請求權限校驗

  2. 請求解析,構建推送任務

  3. 根據推送任務,篩選推送目標用戶,以及獲取推送目標用戶的基本信息

  4. 根據推送策略以及各推送目標用戶的信息選擇推送通道執行推送任務

  5. 各推送通道負責具體的推送操作。

從業務場景看,極光推送平均每秒接收2萬~3萬的推送請求,包括regid、tag、alias、廣播等推送方式。各推送目標的推送目標用戶數量也不同,少則幾個,多則幾千萬甚至上億的目標數量。極光支持多推送通道,客戶可以根據需要選擇使用哪個通道進行推送,各個通道由於服務質量、地域距離等方面的因素,請求耗時、穩定性各有不同,此外還有各自的限速邏輯。業務面臨着很大的挑戰:

接收外部推送請求數大,峯值尖刺甚至可能翻倍

一個推送請求可能產生大量的消息,例如一個廣播或者一個大tag推送,有千萬級別的目標用戶,意味着一個推送請求擴大爲千萬級別的系統內部請求。

整個系統中同時處理的消息體量非常大,常態化的業務峯值超過千萬級別,並且一天時間有多個峯值,不可精確預測。

處理流程中涉及多個處理環節,各個環節的處理速度並不相同,甚至有可能有巨大的差異,例如某些推送通道處理快,某些通道推送處理相對慢。

推送系統如何使用事件驅動提升系統的整體性能
從客戶的需求和產品需求出發,希望每個請求能夠快速、正確地響應並處理,能夠及時地把消息推送給每個目標用戶。因此我們需要解決大量消息以最快的速度推送的問題。

從業務的角度看,可以從租戶分級、租戶隔離、推送方式、推送目標規模等維度進行部署隔離,減小各租戶、各請求間的相互影響,更加快速更加穩定地處理整個推送請求,提供更好的服務質量。

從純技術角度看,採用了多種技術手段和策略,包括緩存優化、異步處理、並行處理等,提升整體性能,實現更高效的推送操作和更好的系統穩定性。

其中採用事件驅動架構來組織整個處理流程,並行、異步處理,實現系統整體性能的提升,並且在突增流量、異常處理方面都能夠很方便地應對。

推送流程的EDA實現
首先,將上述流程簡化爲多個核心處理環節,並構建爲服務,通過消息中間件進行交互。

pushAPI 接收請求,構建推送任務

segmentGateway 篩選推送目標用戶,選擇推送通道,執行推送任務

pushChannel 負責各個推送通道的推送操作,其中包含多個具體的推送通道。

各服務基於事件傳遞狀態轉移 (Event Carried State Transfer)或者事件通知(Event Notification)模式生成事件消息,然後投遞到消息中間件中。同時各服務通過消息隊列或者訂閱的方式從消息中間件消費消息,根據實際需要由消息中間件推送事件消息給消費者或者由消費者主動拉取事件消息。對於重複消息的處理,通常有Exactly once和At least once +業務冪等性處理,建議以第二種方式處理。

注:消息中間件的選型、消息投遞服務質量的原理不在本文的描述範圍,未展開說明。

pushAPI接收推送請求,生成推送任務事件消息,然後投遞到消息中間件。消息中間件根據相關信息發送到指定隊列中。

segmentGateway消費指定隊列,消費其中的事件消息。經過處理後(查詢目標用戶和相關基本信息),批量填充各推送通道的目標用戶到推送任務,並生成新的推送任務事件消息投遞到消息中間件中。消息中間件根據相關信息發送到各推送通道相關的隊列中。

pushChannel的各推送通道服務消費各自的隊列,執行推送操作。

以上流程中,事件消息的生產者不需要消費者的處理結果,消費者也不依賴生產者,完全解耦。

EDA解決推送系統的痛點
並行處理:各服務多節點部署,並行處理請求/消息,當服務出現性能不足以處理業務時,K8S環境下增加節點副本數橫向擴容即可;此外同一個推送請求通過不同推送通道推送時,多個推送通道並行推送消息。

異步處理:各服務專注自己的業務邏輯,不依賴業務下游,通常也不受下游的影響,無需等待處理結果,整個流程異步處理,減少空閒等待時間,可以最大化利用資源。

異常處理:當有突增流量時,請求流量壓力過大,超過了某個處理環節的所有服務節點的處理能力;或者某個推送通道因爲網絡抖動、網絡中斷等處理慢。這些服務節點作爲消息中間件的消費者,因爲處理能力不足或者處理變慢,未來得及處理的請求堆積在消息中間件,等待擴容或者採取其他處理措施。緩存請求到消息中間件中,從某種程度上也是背壓(Back Pressure)模式的一種處理方式,當然還可以進一步的向上遊反饋負載壓力信息,由上游採取處理措施。例如大量消息需要推送到蘋果的推送服務,由於網絡波動或者蘋果服務器限流,可能出現推送變慢,這個時候推送iOS消息可能會堆積在消息中間件中;其他推送通道並不受此影響,依然能夠正常地快速推送消息給其他通道。

其他:鬆散耦合使各服務更加獨立,在進行業務變更時(包括代碼邏輯變更和發佈變更)通常影響面很小,某些情況下甚至能夠不影響上下游邏輯,例如某些推送通道沒有進行推送速率的限制,當增加限速邏輯時隻影響該通道的服務,對於其他通道和上游服務都不影響。

藉助EDA,極光推送能夠輕鬆處理高併發推送請求,實現數千萬級別的消息的快速推送,有更大的彈性應對不可預測的、更大流量的消息推送,以及有更好的異常處理能力。

未來的展望:ServiceMesh/EvenMesh混合架構,統一平臺化
實際上,在極光推送系統中,同時存在2種通信方式,例如在上面的推送流程中,需要根據推送方式獲取推送目標用戶以及相關基本信息,需要從其他子系統服務通過RPC進行查詢獲取結果。整個推送系統的其他功能也是如此,根據業務場景、數據/業務量級做權衡取捨,選擇合適的架構模式來構建系統,保證系統整體性能以及系統的可用性、可維護性。

爲了讓開發者更專注地處理核心的業務代碼邏輯,減少各種通信交互的處理細節(例如超時處理、限流等),目前請求/響應的模式比較主流的做法是Service Mesh,並且經歷了Sidecar/Proxyless/Sidecarless幾種模式的發展,也做了各種權衡取捨。

EDA也有相對應的模式,Event Mesh就是其中之一,通過創建能夠高效可靠地處理任務的網狀代理網絡,解決大規模事件驅動架構的挑戰,包括事件路由、發現和交付,實現跨複雜分佈式系統的事件驅動通信。

我們的推送系統實際上是混合2個通信方式的架構,更理想、更適合我們的架構應該是二者並存。

我們也持續關注相關技術,在充分驗證的情況下引入相關技術,保持架構持續更新優化,避免架構腐化,保證推送系統的高性能、高可用性、高可維護性。

關於極光
極光(Aurora Mobile,納斯達克股票代碼:JG)成立於2011年,是中國領先的客戶互動和營銷科技服務商。成立之初,極光專注於爲企業提供穩定高效的消息推送服務,憑藉先發優勢,已經成長爲市場份額遙遙領先的移動消息推送服務商。隨着企業對客戶觸達和營銷增長需求的不斷加強,極光前瞻性地推出了消息雲和營銷雲等解決方案,幫助企業實現多渠道的客戶觸達和互動需求,以及人工智能和大數據驅動的營銷科技應用,助力企業數字化轉型。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章