本文由vivo 互聯網服務器團隊Yu Quan分享,本文收錄時有內容修訂和重新排版。
1、引言
如今,Android端的即時通訊IM這類應用想實現離線消息推送,難度越來越大(詳見《Android P正式版即將到來:后臺應用保活、消息推送的真正噩夢》、《Android保活從入門到放棄:乖乖引導用戶加白名單吧》)。
于是,使用手機廠商自建的ROOM級消息推送通道進行IM離線消息推送是個不得不面對的問題,我們也正好借此文機會,一窺主流手機廠商的ROOM級推送通道的技術實現吧。
vivo手機的廠商級消息推送系統的現狀是最高推送速度140w/s,單日最大消息量200億,端到端秒級在線送達率99.9%。同時推送系統具備不可提前預知的突發大流量特點。
本文將要分享的是vivo技術團隊針對消息推送系統的高并發、高時效、突發流量等特點,從長連接層容災、邏輯層容災、流量容災、存儲容災等方面入手,如何保證百億級廠商消息推送平臺的高可用性的。
* 推薦閱讀:vivo技術團隊分享的另一篇消息推送技術文章《vivo手機上的系統級消息推送平臺的架構設計實踐》。
2、推送系統介紹
vivo推送平臺是vivo公司向開發者提供的消息推送服務,通過在云端與客戶端之間建立一條穩定、可靠的長連接,為開發者提供向客戶端應用實時推送消息的服務,支持百億級的通知/消息推送,秒級觸達移動用戶。
推送系統主要由3部分組成:
其中,長連接負責與用戶手機終端建立連接,及時把消息送達到手機終端。
推送系統的特點是:
下面將針對這幾個方面來分享我們的技術實踐。
3、長連接層容災的技術實現
長連接是推送系統最重要的部分,長連接的穩定性直接決定了推送系統的推送質量和性能。因此,需要對長連接層做好容災和實時調度能力。
3.1面臨的問題
原有推送系統架構是長連接層都部署在華東,所有vivo IDC邏輯節點通過VPC與華東的Broker建立連接,手機端跟華東的broker進行長連接通信。
這種部署方式存在以下問題。
1)問題一:華北、華南手機都需要連接華東的Broker,地域跨度大,長連接網絡穩定性和時效性相對較差。
2)問題二:邏輯層跟華東的Broker之間由一條VPC連接,隨著業務的發展,推送流量越來越大,帶寬會出現瓶頸,有超限丟包的風險。另外當該VPC出現故障時,會造成全網消息無法送達。
注:長連接層節點名為Broker。
原始長連接架構圖:
3.2解決方法
基于以上架構存在問題,我們對架構進行了優化。即將Broker進行三地部署,分別部署在華北、華東、華南。
華北、華東、華南三地用戶采用就近接入方式。
優化后的架構,不僅可以保證長連接網絡穩定性和時效性。同時具有較強的容災能力,華東、華南Broker通過云網跟華北Broker連接,華北Broker通過VPC與vivo IDC連接。當華北、華東、華南某個地區Broker集群故障或者公網故障,不會影響到全網設備收發消息。
三地部署后的架構圖:
3.3進一步優化
但是上述這種方式還是存在一個問題,就是某個地區Broker集群故障或者公網故障,會出現該區域部分設備無法收到推送消息的情況。
針對上述單個地區異常導致該區域部分設備無法收到推送消息的問題,我們設計了一套流量調度系統,可以做到實時流量調度和切換。global scheduler節點負責策略調度和管理。
vivo phone進行注冊時:dispatcher會下發多個地區的ip地址,默認情況下,進行就近連接。單多次連接失敗后,嘗試連接其他ip。當某個地區Broker出現長連接數瓶頸或者VPC出現故障,可以通過global scheduler節點下發策略,讓該故障地區的設備重新從dispatcher獲取新的ip集的ip,與其他地區Broker建立長連接,邏輯節點下發消息到重連后的Broker。等到該地區恢復后,可以重新再下發策略,進行回調。
流量調度系統圖:
4、邏輯層容災的技術實現
長連接層做好容災后,邏輯層也需要做相應容災。
之前我們邏輯層都部署在一個機房,不具備機房間容災能力,當一個機房出現斷電風險,會出現服務整體不可用問題,因此我們做"同城雙活"部署方案改造。
邏輯層單活架構:
邏輯層分別在vivo IDC1和vivo IDC2進行部署,網關層根據路由規則將流量按照一定比例分別下發到兩個IDC,實現邏輯層同城雙活。
我們發現:數據中心還是只有一個,部署在vivo IDC1,根據成本、收益,以及多數據中心數據同步延遲問題綜合考慮,數據中心暫時還是以單數據中心為主。
邏輯層雙活架構:
5、流量容災的技術實現
5.1概述
做好系統架構的容災能力后,推送系統的網關層還需要應對突發流量做相應的應對措施,做好流量控制,保證系統穩定性。歷史上,我們曾經因為熱點和突發新聞事件,并發推送流量巨大,導致服務出現異常,可用性降低問題。
為了應對突發大流量,保證突發流量的情況下,系統可用性不變,同時能兼顧性能和成本。為此,我們分別對比了設計了以下兩種方案。
5.2常規方案
常規的方案是一般是根據歷史情況估算冗余部署大量機器,來應對突發流量。
單這種方式成本較高,突發流量可能只持續5分鐘或更短時間,而系統為了滿足5分鐘突發流量,需要冗余部署大量機器。
一旦流量超過了部署機器可承擔的上限,無法及時擴容,可能導致可用性下降,甚至出現雪崩效應。
傳統方案下的推送架構:
那如何設計一套既可以控制成本,面對突發大流量彈性擴容,又保證消息不漏并兼顧推送性能的方案呢?
5.3優化方案
優化后的方案:
- 1)在原有架構的基礎上,在接入層增加緩沖通道,當流量洪峰到來時,對于系統可處理的上限能力外的流量,打入緩沖隊列;
- 2)通過消息隊列形式,增加bypass接入層,限速消費消息隊列;
- 3)在流量洪峰過去后,提升bypass消費速度,處理緩存隊列消息;
- 4)bypass接入層通過docker部署,支持動態擴縮容,默認最小化集群,當消息隊列積壓很多,并且下游有能力處理時,提升消費速度,bypass根據CPU負載動態擴容,快速消費消息隊列;
- 5)處理完畢后動態縮容。
消息隊列:選用吞吐量較大的KAFKA中間件,并且與離線計算KAFKA集群共用,能充分利用資源。
bypass接入層:采用docker部署,支持根據CPU負載和時間動態擴縮容。默認最小集群部署。對于已知的流量高峰時段,可以提前擴容服務,保證流量快速處理。未知時段流量高峰,可以bypass接入層,根據CPU負載情況進行動態擴縮容。
增加緩存隊列后的推送架構:
5.4進一步優化
進行上述改造后:還存在一個問題,就是如何進行接入層全局控速。
我們采用的方式是:收集下游推送節點的推送流量情況。
比如:流量達到系統可承受上限的80%時下發限速指令,調整接入層推送速度。讓消息先積壓在消息隊列,等到下游流量降低之后,下發解除限速指令,讓bypass接入層加速消費消息隊列,進行推送。
增加控速后的推送架構:
優化后方案與傳統方案對比:
6、存儲容災的技術實現
6.1問題
做好并發流量控制后,能很好的預發突發熱點問題。但在推送系統內部,由于使用Redis集群緩存消息,出現過因為Redis集群故障導致消息無法及時送達問題。
因此:我們考慮對Redis集群做相關容災方案設計,實現系統在Redis集群故障期間,也能及時推送消息并保證消息不丟失。
推送消息體緩存在Redis集群中,推送時從Redis中獲取消息體,如果Redis集群宕機,或者內存故障,會導致離線消息體丟失。
6.2方案
原有消息流程:
1)方案一:
引入另一個對等Redis集群,采用推送雙寫方式,雙寫兩個Redis集群。該方案需要冗余部署規模對等的備Redis集群。推送系統需要雙寫Redis操作。
2)方案二:
原有Redis集群,采用RDB+AOF方式同步到另一個備Redis集群。
該方案不在需要推送系統雙寫Redis改造,直接利用將原有Redis集群數據同步到另一個備Redis集群。也需要冗余部署規模對等的備Redis集群。可能存在部分數據同步延遲導致推送失敗問題。
3)方案三:
應用另一個分布式存儲系統,磁盤KV,兼容Redis協議,同時具有持久化能力。可以保證消息體不丟失。但是為了節省成本,不再直接使用Redis集群對等資源。
而是根據推送特點,推送分為單推、群推。單推是一對一推送,一個用戶一條消息體。群推是一對多推送,一個消息體對應多個用戶。
群推往往是任務級別推送。因此我們使用一個相對小一些的磁盤KV集群,主要用于冗余存儲,群推消息體,即任務級別的消息。對于單推,還是只保存到Redis中,不進行冗余存儲。
如果Redis集群故障,對于單推消息,推送系統可以攜帶消息體往下游推送,確保消息可以繼續下發。對于群推消息,因為消息體冗余存儲在磁盤KV中,當Redis集群故障后,可以降級到讀取磁盤KV。
6.3優化
方案三還存在一個問題,就是磁盤KV的寫入性能和Redis集群不是一個數量級,特別是時延,磁盤KV在平均在5ms左右。
而Redis集群卻在0.5ms。如果在推送系統對群推消息體進行雙寫。這個時延是不能接受的。
因此只能采用異步寫入磁盤KV的方式。
這里將備份群推消息體,先寫入消息中間件KAFKA,由bypass節點消費KAKFA進行異步寫入磁盤KV。這樣在使用的災備磁盤KV資源較少的前提下,保證推送系統的高并發能力,同時可以保證群推消息體不丟失,Redis異常時,單推消息攜帶消息體推送,群推消息體讀取磁盤KV。
存儲容災方案對比:
7、本文小結
本文從長連接層容災、邏輯層容災、流量容災、存儲容災等幾個方面講述了推送系統容災建設過程。系統容災需要根據業務發展,成本收益,實現難度等多方面考慮。
當前我們長連接層已具備三地部署,邏輯層具備同城雙活,數據中心為單數據中心。后續我們會持續研究和規劃雙數據中心,兩地三中心部署架構方式來逐步加強推送系統容災能力。
8、參考資料
[1] vivo手機上的系統級消息推送平臺的架構設計實踐
[2] 魅族2500萬長連接的實時消息推送架構的技術實踐分享
[3] 專訪魅族架構師:海量長連接的實時消息推送系統的心得體會
[4] 百萬在線的美拍直播彈幕系統的實時推送技術實踐之路
[5] 京東京麥商家開放平臺的消息推送架構演進之路
[6] 解密“達達-京東到家”的訂單即時派發技術原理和實踐
[7] 長連接網關技術專題(四):愛奇藝WebSocket實時推送網關技術實踐
[8] 喜馬拉雅億級用戶量的離線消息推送系統架構設計實踐
[9] 微信直播聊天室單房間1500萬在線的消息架構演進之路
[10] 百度直播的海量用戶實時消息系統架構演進實踐
[11] 消息推送技術干貨:美團實時消息推送服務的技術演進之路
[12] 技術干貨:從零開始,教你設計一個百萬級的消息推送系統
9、vivo技術團隊分享的其它文章
《IM消息ID技術專題(七):深度解密vivo的自研分布式ID服務(魯班)》
《直播系統聊天技術(八):vivo直播系統中IM消息模塊的架構實踐》
《IM跨平臺技術學習(三):vivo的Electron技術棧選型、全方位實踐總結》
《vivo手機上的系統級消息推送平臺的架構設計實踐》
(本文已同步發布于:http://www.52im.net/thread-4416-1-1.html)