微信多點登錄與QQ消息漫游架構(gòu)隨想

2018-09-06 17:44 更新

【需求緣起】

之前的一些文章簡單介紹了“單人消息”》《“離線消息”》《“群消息”》《“用戶狀態(tài)”》的一些相關(guān)技術(shù)(點擊上面的link直接閱讀),今天來聊一聊“多點登陸”與“消息漫游”。


提問:什么是多點登錄?

回答:以微信為例,可以PC端,phone端同時登錄,同時收發(fā)消息。

需要注意的是,一個端只能登錄一個實例,例如同一個QQ號,在pc1上登錄,再到pc2上登錄,后者會把前者踢出,pc1會收到通知“你已在別處登錄xxoo”。


提問:什么是消息漫游?

回答:在任何一個終端的任何一個實例登錄qq,都能夠拉取到所有歷史聊天消息,這個就是消息漫游。

微信目前只支持“多點登錄”同時收發(fā)在線消息,沒有實現(xiàn)“消息漫游”,潛臺詞是:登出手機微信,登錄PC微信,聊天,再登錄手機微信,是看不到歷史消息的。


【架構(gòu)回顧】

常見即時通訊系統(tǒng)架構(gòu)抽象

整個即時通訊架構(gòu)可以抽象成這么幾層:

(1)客戶端:例如pc微信,手機qq

(2)服務(wù)端:

(2.1)入口層gate集群:能夠水平擴展,保持與客戶端的連接

(2.2)邏輯層logic、路由層router集群:高可用可擴展,實現(xiàn)業(yè)務(wù)邏輯,進行消息的路由

(2.3)cache:高可用cache集群,用來存儲用戶的在線狀態(tài),與接入節(jié)點(用戶具體連接在哪個gate節(jié)點)

(2.4)db固化存儲消息,群信息,好友關(guān)系鏈等信息


一個典型的消息投遞流程如上圖步驟1-5:

(1)用戶A登錄在gate1上,發(fā)出消息

(2)gate1將消息給logic/router

(3)logic/router查詢接收方的在線狀態(tài)(B在線,C不在線)

(4)例如接收方C不在線,存儲離線

(4)例如接收方B在線,且登錄在gate2上,消息投遞給gate2

(5)gate2將消息投遞給B

當(dāng)然,單對單消息有一系列應(yīng)用層超時、重傳、確認、去重的機制,這不是本文的重點,不進行展開,細節(jié)詳見《微信為什么不丟消息》。


【接收方多點登陸】

接收方多點登陸

接收方多點登錄,pc也登錄,phone也登錄,后一端登錄不會將前一端踢出,cache中存儲狀態(tài)與登錄點時,不再以user_id為key,改為以user_id+終端類型為key即可。

B:online(狀態(tài)),gate2(登錄點)

改為

B+pc:online(狀態(tài)),gate2(登錄點)

B+phone:online(狀態(tài)),gate3(登錄點)


當(dāng)用戶A給用戶B發(fā)送消息時,取出所有B的登錄點,進行消息群發(fā)即可(如上圖中步驟4與步驟5)。

【發(fā)送方多點登陸】

有朋友可能要問,發(fā)送方和多點登錄有什么關(guān)系?

假設(shè)用戶A登錄了兩個點,A1和A2;用戶B登錄了兩個點B1和B2

A(A1發(fā)出的)發(fā)送消息給B(B1和B2)

B(B1發(fā)出的)發(fā)送消息給A(A1和A2)

不就可以了么?

其實不然,A(A1發(fā)出的)發(fā)送消息給B(B1和B2),B(B1發(fā)出的)發(fā)送消息給A(A1和A2)

A2端雖然收到了所有B回復(fù)的消息,但消息其實是在A1端發(fā)出的,故A2端只知道聊天消息的一半(所有B的回復(fù)),缺失了聊天的上下文(所有A1端的發(fā)出)

故,如果發(fā)送方也進行了多點登錄,發(fā)送出去的任何消息,除了要投遞給多點登錄的接收方,還需要投遞給多點登錄的發(fā)送方。

發(fā)送方多點登錄

如上圖,發(fā)送方A和接收方B都進行了多點登陸,cache中存儲的信息為:

A+pc:online(狀態(tài)),gate0(登錄點)

A+phone:online(狀態(tài)),gate1(登錄點)

B+pc:online(狀態(tài)),gate2(登錄點)

B+phone:online(狀態(tài)),gate3(登錄點)


當(dāng)用戶A(phone端)給用戶B發(fā)送消息時,除了要投遞給B的所有多點登錄端,還需要投遞給A多點登陸的其他端(pc端),如上圖中步驟4與步驟5。

只有這樣,才能在所有用戶的所有端,恢復(fù)與還原雙方聊天的上下文。


【消息漫游】

如果業(yè)務(wù)不需要支持“消息漫游”的功能,對于在線消息,如果用戶接收到,是不需要存儲到數(shù)據(jù)庫的。但如果要支持“換一臺機器也能看到歷史的聊天消息”,就需要對所有消息進行存儲了。

消息漫游:所有消息均存儲

消息投遞如上圖,用戶A發(fā)送消息給用戶B,雖然B在線,仍然要增加一個步驟2.5,在投遞之前進行存儲,以備B的其他端登陸時,可以拉取到歷史消息。

消息漫游:客戶本地last_msg_id(time)拉消息

消息拉取如上圖,原本不在線的B(phone端),又重新登錄了,ta怎么拉取歷史消息?只需要在客戶端本地存儲一個上一次拉取到的msg_id(time),到服務(wù)端重新拉取即可

這里還有個問題,由于服務(wù)端存儲所有消息成本是非常高的,所以一般“消息漫游”是有時間(或者消息數(shù))限制,不能拉取所有所有幾年前的歷史消息,只能拉取3個月內(nèi)的云端消息。


【總結(jié)】

“多點登錄”是指多個端同時登錄一個帳號,同時收發(fā)消息,關(guān)鍵點是:

(1)需要在服務(wù)端存儲同一個用戶多個端的狀態(tài)與登陸點

(2)發(fā)出消息時,要對發(fā)送方的多端與接收端的多端,都進行消息投遞


“消息漫游”是指一個用戶在任何端,都可以拉取到歷史消息,關(guān)鍵點是:

(1)所有消息存儲在云端

(2)每個端本地存儲last_msg_id,在登錄時可以到云端同步歷史消息

(3)云端存儲所有消息成本較高,一般會對歷史消息時間(或者條數(shù))進行限制


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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號