58到家通用實(shí)時(shí)消息平臺(tái)架構(gòu)細(xì)節(jié)(Qcon2016)

2018-09-06 17:47 更新
2016Qcon北京,業(yè)務(wù)核心架構(gòu)場(chǎng),《58到家通用實(shí)時(shí)消息平臺(tái)架構(gòu)細(xì)節(jié)》。

一、解決什么問(wèn)題 + 難點(diǎn)

解決什么業(yè)務(wù)問(wèn)題

(1)端到云的實(shí)時(shí)上報(bào)需求:58速運(yùn)司機(jī)端GPS實(shí)時(shí)上報(bào)

(2)云到端的實(shí)時(shí)推送需求:58速運(yùn)司機(jī)訂單實(shí)時(shí)推送

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

難點(diǎn):

(1)APP無(wú)線環(huán)境下消息可達(dá)性

(2)通用性,平臺(tái)實(shí)現(xiàn)盡量與業(yè)務(wù)解耦


二、傳統(tǒng)解決方案與潛在不足

【端到云:http輪詢(xún)上報(bào)GPS消息】

傳統(tǒng):端到云的上報(bào)1

方案一:直接通過(guò)業(yè)務(wù)線web-server寫(xiě)DB

傳統(tǒng):端到云的上報(bào)2

方案二:通用web-server層調(diào)用業(yè)務(wù)服務(wù)層寫(xiě)DB

潛在不足

(1)http短連接代價(jià)高(反復(fù)創(chuàng)建與銷(xiāo)毀連接)

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


【云到端:通過(guò)第三方push或者推送服務(wù)】

方案一:通過(guò)APNs或者米推等第三方推送

方案二:通過(guò)自己搭建mqtt服務(wù)推送

潛在不足

(1)第三方可達(dá)性與實(shí)時(shí)性無(wú)法保證,第三方會(huì)進(jìn)行推送限速

(2)mqtt可用性是個(gè)問(wèn)題


【端到端:結(jié)合上面兩種方法實(shí)現(xiàn)】

傳統(tǒng)方案往往可以通過(guò)結(jié)合【端到云】與【云到端】來(lái)結(jié)合解決【端到端】的實(shí)時(shí)消息推送問(wèn)題。

三、通用實(shí)時(shí)消息平臺(tái)實(shí)現(xiàn)細(xì)節(jié)

業(yè)務(wù)的分析與抽象:司機(jī)、用戶(hù)、商家、客服均為“在線業(yè)務(wù)

【端到云的優(yōu)化】

端到云的優(yōu)化

傳統(tǒng)方案潛在的問(wèn)題:http輪詢(xún)效率不高,web-server性能有限

優(yōu)化TIPS消息平臺(tái)使用tcp長(zhǎng)連接(如上圖)


消息平臺(tái)與業(yè)務(wù)線app-server耦合

潛在的問(wèn)題:消息平臺(tái)與業(yè)務(wù)線app-server耦合,需要switch case業(yè)務(wù)線類(lèi)型來(lái)分發(fā)投遞消息,新增業(yè)務(wù)線需要新增RPC調(diào)用(如上圖)

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

使用消息總線msg-queue解耦
可以看到,使用消息總線后,新增消息發(fā)送方,消息平臺(tái)只需要配置消息類(lèi)型與消息總線主題的映射關(guān)系,新增的app-server消費(fèi)方訂閱新的主題即可,實(shí)現(xiàn)消息平臺(tái)與業(yè)務(wù)的解耦。

【云到端的優(yōu)化】

潛在的問(wèn)題:可用性問(wèn)題與第三方限速

優(yōu)化TIPS:自己提供消息平臺(tái)集群,提供RPC接口,實(shí)現(xiàn)“云到端”的消息通道

云到端”的消息通道
這里要注意的是,“端到云”使用消息總線,是為了業(yè)務(wù)解耦。“云到端”直接使用RPC接口,也是為了業(yè)務(wù)解耦,新增消息推送方,消息平臺(tái)無(wú)需改動(dòng)代碼。

潛在的問(wèn)題:不少司機(jī)推送訂單無(wú)回復(fù),搶單率比預(yù)期的低

優(yōu)化TIPS引入狀態(tài)實(shí)時(shí)存儲(chǔ),只有“在線”狀態(tài)的用戶(hù)才推送消息

引入狀態(tài)實(shí)時(shí)存儲(chǔ)

【端到端的優(yōu)化】

端到端的優(yōu)化

如果業(yè)務(wù)無(wú)關(guān),則直接通過(guò)tcp通道投遞;如果業(yè)務(wù)相關(guān),發(fā)送方先來(lái)一個(gè)“端到云”的投遞(通過(guò)mq),業(yè)務(wù)服務(wù)器處理再反向來(lái)一個(gè)“云到端”的投遞(RPC)給接收方


潛在問(wèn)題:如果接收方不在線怎么辦

優(yōu)化TIPS增加DB存儲(chǔ)離線消息


潛在的問(wèn)題:無(wú)線環(huán)境下經(jīng)常網(wǎng)絡(luò)不穩(wěn)(例如進(jìn)出電梯斷網(wǎng)),消息經(jīng)常丟失

優(yōu)化TIPS:消息平臺(tái)收到消息先落地?cái)?shù)據(jù)庫(kù),接收方收到后應(yīng)用層ACK再刪除,以保證不丟失

端到端的優(yōu)化2

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

(1)發(fā)送發(fā)將消息發(fā)給消息平臺(tái)

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

(3)消息平臺(tái)回復(fù)發(fā)送方消息發(fā)送成功(此時(shí)和接收方是否接到無(wú)關(guān))

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

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

(5)消息平臺(tái)將消息刪除

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

可以看到,是使用“應(yīng)用層ACK來(lái)解決消息可達(dá)性問(wèn)題的


潛在問(wèn)題:發(fā)送方?jīng)]有收到第3步驟中的消息平臺(tái)回復(fù)怎么辦?

優(yōu)化TIPS發(fā)送方重發(fā)(服務(wù)器無(wú)狀態(tài))


潛在問(wèn)題:接收方收到重發(fā)的冗余消息怎么辦?

優(yōu)化TIPS接收方去重(可以做到服務(wù)端完全無(wú)狀態(tài),只需要簡(jiǎn)單投遞消息即可)


【分層架構(gòu)說(shuō)明】
分層架構(gòu)

整個(gè)系統(tǒng)的分層架構(gòu)如上圖(本文最重要的2張圖之二),整個(gè)消息平臺(tái)系統(tǒng)由:

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

(2)msg-gate,整個(gè)消息平臺(tái)的tcp接入門(mén)戶(hù),保持tcp長(zhǎng)連接,初步攻防,加解密,壓縮解壓縮

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

(4)redis,高可用redis集群存儲(chǔ)用戶(hù)在線狀態(tài)online/offline,以及用戶(hù)在哪一臺(tái)msg-gate接入(如果在線)

(5)DB,存儲(chǔ)離線消息

非消息平臺(tái)的幾個(gè)業(yè)務(wù)部分

(1)APP:業(yè)務(wù)方APP,可以有多個(gè),通過(guò)msg-sdk來(lái)接入消息平臺(tái)

(2)mq:消息平臺(tái)通過(guò)mq來(lái)給業(yè)務(wù)方服務(wù)器發(fā)“端到云”的消息

(3)app-server:業(yè)務(wù)方后端,可以有多個(gè),通過(guò)mq接收“端到云”的消息,通過(guò)RPC發(fā)送“云到端”的消息


【對(duì)外提供的接口說(shuō)明】

消息平臺(tái)對(duì)業(yè)務(wù)方提供的接口是很少很通用的接口。

msg-sdk對(duì)APP提供的核心接口有:

(1)login:接入消息平臺(tái)

(2)logout:登出消息平臺(tái)

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

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

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

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

消息平臺(tái)對(duì)app-server提供的核心接口有:

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

其他業(yè)務(wù)方不需要關(guān)注,是msg-sdk與消息平臺(tái)之間的內(nèi)部接口有:

(1)keepalive:用于msg-sdk與消息平臺(tái)的連接保持(對(duì)業(yè)務(wù)方透明)

(2)c2c-ack:用戶(hù)c2c接口的應(yīng)用層ack接口(對(duì)業(yè)務(wù)方透明)


【如何實(shí)現(xiàn)跨帳號(hào)體系的聊天】

既然是通用的消息平臺(tái),如何實(shí)現(xiàn)跨帳號(hào)體系的消息發(fā)送呢(即如何實(shí)現(xiàn)qq與旺旺的聊天)?

解決方案:不再使用uid作為整個(gè)系統(tǒng)運(yùn)行的key,而使用domain+uid,或者appid+uid來(lái)作為整個(gè)系統(tǒng)運(yùn)行的key

潛在耦合點(diǎn):這樣的話,login接口的邏輯處理,消息平臺(tái)需要switch case (domain或者appid)來(lái)進(jìn)行不同的登錄驗(yàn)證,與業(yè)務(wù)有一定的耦合,不過(guò)新增帳號(hào)體系的頻度很低,遠(yuǎn)比新增消息類(lèi)型低


【協(xié)議的擴(kuò)展性設(shè)計(jì)】

APP本質(zhì)是cs架構(gòu),一旦放出去的版本就很難收回來(lái),其兼容系要求遠(yuǎn)比bs架構(gòu)難,如何做到新增功能的同時(shí),還能方便的兼容歷史舊版APP呢?

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

解決方案協(xié)議使用定長(zhǎng)包頭 + 變長(zhǎng)包體,使用命令號(hào)cmd來(lái)擴(kuò)展新接口【這個(gè)變化對(duì)業(yè)務(wù)層是透明的,是msg-sdk與消息平臺(tái)之間的事情】

(2)對(duì)于同一個(gè)接口,能否增加參數(shù),而不影響舊版本的APP?

解決方案使用可擴(kuò)展的序列化協(xié)議,例如protobuffer【protobuffer這個(gè)東西也對(duì)業(yè)務(wù)線透明】

(3)對(duì)于業(yè)務(wù)方,有很多種類(lèi)的消息類(lèi)型,有很多復(fù)雜的業(yè)務(wù)需求,如何保證業(yè)務(wù)擴(kuò)展性的同時(shí),又不會(huì)增加消息平臺(tái)的復(fù)雜性,并對(duì)舊版本APP兼容?

例如業(yè)務(wù)線可能有這樣的潛在需求:

a)推送一個(gè)運(yùn)營(yíng)消息

b)推送消息內(nèi)容支持字體、字號(hào)、加粗、顏色

c)推送消息支持圖片

d)業(yè)務(wù)支持“窗口震動(dòng)”,以及“對(duì)方正在輸入......”等需求

解決方案使用可擴(kuò)展的消息體協(xié)議(對(duì)消息平臺(tái)透明),例如xml/json來(lái)支持可擴(kuò)展的多樣消息類(lèi)型,并對(duì)舊版本APP兼容

<msg>
<type>1</type>
<fond>宋體</font>
<content>hello, world!</content>
<pic>http://pic.daojia.com/hello.jpg</pic>
</msg>
使用這種消息內(nèi)容協(xié)議,能保證:擴(kuò)展性好、舊版本兼容、對(duì)消息平臺(tái)透明等諸多好處,強(qiáng)烈建議使用

四、分布式架構(gòu)細(xì)節(jié)

抱歉,主持人提醒時(shí)間已到,分布式架構(gòu)擴(kuò)展性、負(fù)載均衡性、可用性、一致性的問(wèn)題線下和大家分享,先放一個(gè)分布式架構(gòu)圖吧:

分布式系統(tǒng)架構(gòu)

五、總結(jié)

(1)“端到云”消息投遞TCP消息通道,消息總線業(yè)務(wù)解耦

(2)“云到端”消息投遞提供RPC接口,引入狀態(tài)存儲(chǔ)

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

端到端的優(yōu)化2
(4)“端到端”消息投遞技巧
        a)先存離線消息防丟失
        b)ACK機(jī)制保證可達(dá)
        c)發(fā)送方消息重發(fā)

        d)接收方消息去重

(5)可擴(kuò)展協(xié)議設(shè)計(jì)

        a)定長(zhǎng)包頭,變長(zhǎng)包體,隨時(shí)增加接口
        b)可擴(kuò)展序列化協(xié)議,隨時(shí)變化接口

        c)可擴(kuò)展消息協(xié)議,隨時(shí)增加類(lèi)型

(6)支持跨帳號(hào)體系聊天(多個(gè)域)使用domain(或者appid)+uid作為綜合key

(7)分層架構(gòu)如下圖

分層架構(gòu)


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)