58到家通用實時消息平臺架構細節

一、解決什麼問題 + 難點

解決什麼業務問題

(1)端到雲的實時上報需求:58速運司機端GPS實時上報

(2)雲到端的實時推送需求:58速運司機訂單實時推送

(3)端到端的聊天消息需求:用戶、商戶、客服之間的聊天溝通

難點:

(1)APP無線環境下消息可達性

(2)通用性,平臺實現儘量與業務解耦


二、傳統解決方案與潛在不足

【端到雲:http輪詢上報GPS消息】

方案一:直接通過業務線web-server寫DB



方案二:通用web-server層調用業務服務層寫DB

潛在不足

(1)http短連接代價高(反覆創建與銷燬連接)

(2)web-server層吞吐量較低(每秒處理千級別請求)


【雲到端:通過第三方push或者推送服務】

方案一:通過APNs或者米推等第三方推送

方案二:通過自己搭建mqtt服務推送

潛在不足

(1)第三方可達性與實時性無法保證,第三方會進行推送限速

(2)mqtt可用性是個問題


【端到端:結合上面兩種方法實現】


傳統方案往往可以通過結合【端到雲】與【雲到端】來結合解決【端到端】的實時消息推送問題。


三、通用實時消息平臺實現細節

業務的分析與抽象:司機、用戶、商家、客服均爲“在線”業務

【端到雲的優化】


傳統方案潛在的問題:http輪詢效率不高,web-server性能有限

優化TIPS消息平臺使用tcp長連接(如上圖)



潛在的問題:消息平臺與業務線app-server耦合,需要switch case業務線類型來分發投遞消息,新增業務線需要新增RPC調用(如上圖)

優化TIPS使用消息總線msg-queue解耦(如下圖)


可以看到,使用消息總線後,新增消息發送方,消息平臺只需要配置消息類型與消息總線主題的映射關係,新增的app-server消費方訂閱新的主題即可,實現消息平臺與業務的解耦。


【雲到端的優化】

潛在的問題:可用性問題與第三方限速

優化TIPS:自己提供消息平臺集羣,提供RPC接口,實現“雲到端”的消息通道


這裏要注意的是,“端到雲”使用消息總線,是爲了業務解耦。“雲到端”直接使用RPC接口,也是爲了業務解耦,新增消息推送方,消息平臺無需改動代碼


潛在的問題:不少司機推送訂單無回覆,搶單率比預期的低

優化TIPS引入狀態實時存儲,只有“在線”狀態的用戶才推送消息



【端到端的優化】


如果業務無關,則直接通過tcp通道投遞;如果業務相關,發送方先來一個“端到雲”的投遞(通過mq),業務服務器處理再反向來一個“雲到端”的投遞(RPC)給接收方


潛在問題:如果接收方不在線怎麼辦

優化TIPS增加DB存儲離線消息


潛在的問題:無線環境下經常網絡不穩(例如進出電梯斷網),消息經常丟失

優化TIPS:消息平臺收到消息先落地數據庫接收方收到後應用層ACK再刪除,以保證不丟失


如上圖(本文最重要的2張圖之一),整個消息投遞流程爲:

(1)發送發將消息發給消息平臺

(2)消息平臺先將消息落地DB

(3)消息平臺回覆發送方消息發送成功(此時和接收方是否接到無關)

(3)與此同時,並行的把消息投遞給接收方(如果不在線就存離線了)

(4)接收方應用層ACK表示收到了消息

(5)消息平臺將消息刪除

(6)告之接收方ACK已經成功處理

可以看到,是使用“應用層ACK來解決消息可達性問題的


潛在問題:發送方沒有收到第3步驟中的消息平臺回覆怎麼辦?

優化TIPS發送方重發(服務器無狀態)


潛在問題:接收方收到重發的冗餘消息怎麼辦?

優化TIPS接收方去重(可以做到服務端完全無狀態,只需要簡單投遞消息即可)


【分層架構說明】


整個系統的分層架構如上圖(本文最重要的2張圖之二),整個消息平臺系統由:

(1)消息平臺在APP裏的msg-sdk,向APP提供帥氣的接口

(2)msg-gate,整個消息平臺的tcp接入門戶,保持tcp長連接,初步攻防,加解密,壓縮解壓縮

(3)msg-logic,整個消息平臺邏輯處理的部分

(4)redis,高可用redis集羣存儲用戶在線狀態online/offline,以及用戶在哪一臺msg-gate接入(如果在線)

(5)DB,存儲離線消息

非消息平臺的幾個業務部分

(1)APP:業務方APP,可以有多個,通過msg-sdk來接入消息平臺

(2)mq:消息平臺通過mq來給業務方服務器發“端到雲”的消息

(3)app-server:業務方後端,可以有多個,通過mq接收“端到雲”的消息,通過RPC發送“雲到端”的消息


【對外提供的接口說明】

消息平臺對業務方提供的接口是很少很通用的接口。

msg-sdk對APP提供的核心接口有:

(1)login:接入消息平臺

(2)logout:登出消息平臺

(3)c2s:發送client to server“端到雲”的消息

(4)c2c:發送client to client“端到端”的消息

(5)get-offline-msg:拉取離線消息

(6)on-msg-recieved:收到消息的callback回調接口

消息平臺對app-server提供的核心接口有:

(1)s2c:發送server to client“雲到端”的消息

其他業務方不需要關注,是msg-sdk與消息平臺之間的內部接口有:

(1)keepalive:用於msg-sdk與消息平臺的連接保持(對業務方透明)

(2)c2c-ack:用戶c2c接口的應用層ack接口(對業務方透明)


【如何實現跨帳號體系的聊天】

既然是通用的消息平臺,如何實現跨帳號體系的消息發送呢(即如何實現qq與旺旺的聊天)?

解決方案不再使用uid作爲整個系統運行的key,而使用domain+uid,或者appid+uid來作爲整個系統運行的key

潛在耦合點:這樣的話,login接口的邏輯處理,消息平臺需要switch case (domain或者appid)來進行不同的登錄驗證,與業務有一定的耦合,不過新增帳號體系的頻度很低,遠比新增消息類型低


【協議的擴展性設計】

APP本質是cs架構,一旦放出去的版本就很難收回來,其兼容系要求遠比bs架構難,如何做到新增功能的同時,還能方便的兼容歷史舊版APP呢?

(1)如何方便的增加接口?

解決方案協議使用定長包頭 + 變長包體,使用命令號cmd來擴展新接口【這個變化對業務層是透明的,是msg-sdk與消息平臺之間的事情】

(2)對於同一個接口,能否增加參數,而不影響舊版本的APP?

解決方案使用可擴展的序列化協議,例如protobuffer【protobuffer這個東西也對業務線透明】

(3)對於業務方,有很多種類的消息類型,有很多複雜的業務需求,如何保證業務擴展性的同時,又不會增加消息平臺的複雜性,並對舊版本APP兼容?

例如業務線可能有這樣的潛在需求:

a)推送一個運營消息

b)推送消息內容支持字體、字號、加粗、顏色

c)推送消息支持圖片

d)業務支持“窗口震動”,以及“對方正在輸入......”等需求

解決方案使用可擴展的消息體協議(對消息平臺透明),例如xml/json來支持可擴展的多樣消息類型,並對舊版本APP兼容

<msg>

<type>1</type>

<fond>宋體</font>

<content>hello, world!</content>

<pic>http://pic.daojia.com/hello.jpg</pic>

</msg>

使用這種消息內容協議,能保證:擴展性好、舊版本兼容、對消息平臺透明等諸多好處,強烈建議使用


四、分佈式架構細節

抱歉,主持人提醒時間已到,分佈式架構擴展性、負載均衡性、可用性、一致性的問題線下和大家分享,先放一個分佈式架構圖吧:


<廣告>

如果你讀到了這裏,說明對消息平臺還是有點興趣的,58到家消息平臺團隊只有一個同學奇缺人,歡迎有志之士加入

一些說明:base北京,核心團隊,技術導向,Java方向,和58沈劍一個團隊

加入方式:(1)直接在文章下面留言(2)在公衆號回覆“招聘”獲取加盟密鑰

</廣告完畢>

五、總結

(1)“端到雲”消息投遞TCP消息通道,消息總線業務解耦

(2)“雲到端”消息投遞提供RPC接口,引入狀態存儲

(3)“端到端”消息投遞步驟如下圖


(4)“端到端”消息投遞技巧

        a)先存離線消息防丟失

        b)ACK機制保證可達

        c)發送方消息重發

        d)接收方消息去重

(5)可擴展協議設計

        a)定長包頭,變長包體,隨時增加接口

        b)可擴展序列化協議,隨時變化接口

        c)可擴展消息協議,隨時增加類型

(6)支持跨帳號體系聊天(多個域)使用domain(或者appid)+uid作爲綜合key

(7)分層架構如下圖

發佈了33 篇原創文章 · 獲贊 154 · 訪問量 58萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章