微信多点登陆,消息漫游,假如让你来实现?

有朋友问:数据库

  • 微信如何实现手机端、PC端同时登陆,同时收消息?
  • 微信能不能实现,换一个手机,仍能拉取到历史消息?
    这是多点登陆和消息漫游的问题。

什么是多点登陆?

以微信为例,能够PC端,phone端同时登陆,同时收发消息。
画外音:须要注意的是,一个端只能登陆一个实例,例如同一个QQ号,在pc1上登陆,再到pc2上登陆,后者会把前者踢出,pc1会收到通知“你已在别处登陆xxoo”。
微信

什么是消息漫游?

在任何一个终端的任何一个实例登陆,都可以拉取到全部历史聊天消息,这个就是消息漫游。
画外音:微信目前只支持“多点登陆”同时收发在线消息,以及最近几条消息的“消息漫游”,没有实现所有消息的“漫游”。
架构

典型即时通信架构如何?

  • 典型即时通信架构能够抽象成这么几层:
  • 客户端:例如pc微信,手机qq
    服务端:
    入口层gate:保持与客户端的链接;
    逻辑层logic、路由层router:实现业务逻辑,进行消息的路由;
    cache:用来存储用户的在线状态,与接入节点(用户具体链接在哪一个gate节点);
    db:固化存储消息,群信息,好友关系链等信息;
    画外音:都须要考虑高可用,扩展性。
    微信多点登陆,消息漫游,假如让你来实现?
    一个典型的消息投递流程如上图步骤1-5:
    (1) 用户A登陆在gate1上,发出消息;
    (2) gate1将消息给logic/router;
    (3) logic/router查询接收方的在线状态(B在线,C不在线);
    (4.1) 假设接收方C不在线,存储离线;
    (4.2) 假设接收方B在线,且登陆在gate2上,消息投递给gate2;
    (5) gate2将消息投递给B;
    画外音:单对单消息有一系列应用层超时、重传、确认、去重的机制,以保证消息的可靠投递,这不是本文的重点,不进行展开。














实现“接收方”多点登录,架构要作什么调整?
微信多点登陆,消息漫游,假如让你来实现?
接收方多点登陆,pc也登陆,phone也登陆,后一端登陆不会将前一端踢出,cache中存储状态与登陆点时,再也不以user_id为key,改成以user_id+终端类型为key便可。

ide

单点登陆

B:online(状态),gate2(登陆点)优化

多点登录

B+pc:online(状态),gate2(登陆点)
B+phone:online(状态),gate3(登陆点)
spa

当用户A给用户B发送消息时,取出全部B的登陆点,进行消息群发便可(如上图中步骤4与步骤5)。
画外音:接收方多点登陆,比较容易。
架构设计

实现“发送方”多点登录,架构要作什么调整?

有朋友可能要问,发送方和多点登陆有什么关系?
假设:
用户A登陆了两个点,A1和A2;
用户B登陆了两个点,B1和B2;
这样:
A(A1发出的)发送消息给B(B1和B2);
B(B1发出的)发送消息给A(A1和A2);
不就能够了么?






设计

其实否则:
A(A1发出的)发送消息给B(B1和B2);
B(B1发出的)发送消息给A(A1和A2);
可是:
A2端虽然收到了全部B回复的消息,但消息实际上是在A1端发出的,故A2端只知道聊天消息的一半(全部B的回复),缺失了聊天的上下文(全部A1端的发出)。
画外音:这个逻辑有点绕,多看几遍。




router

故,若是发送方也进行了多点登陆,发送出去的任何消息,除了要投递给多点登陆的接收方,还须要投递给多点登陆的发送方。
画外音:发送方发出的消息,也须要发给“发送方”。
微信多点登陆,消息漫游,假如让你来实现?
如上图,发送方A和接收方B都进行了多点登录,cache中存储的信息为:
A+pc:online(状态),gate0(登陆点)
A+phone:online(状态),gate1(登陆点)
B+pc:online(状态),gate2(登陆点)
B+phone:online(状态),gate3(登陆点)






blog

当用户A(phone端)给用户B发送消息时,除了要投递给B的全部多点登陆端,还须要投递给A多点登录的其余端(pc端),如上图中步骤4与步骤5。

只有这样,才能在全部用户的全部端,恢复与还原双方聊天的上下文。
画外音:搞清楚了原理,修改并不难。

实现“消息漫游”,架构要作什么调整?

若是不须要支持“消息漫游”,对于在线消息,若是用户接收到,是不须要存储到数据库的。但若是要支持“换一台机器也能看到历史的聊天消息”,就须要对全部消息进行存储。

微信多点登陆,消息漫游,假如让你来实现?
消息投递如上图,用户A发送消息给用户B,虽然B在线,仍然要增长一个步骤2.5,在投递以前进行存储,以备B的其余端登录时,能够拉取到历史消息。

微信多点登陆,消息漫游,假如让你来实现?
消息拉取如上图,本来不在线的B(phone端)从新登陆了,怎么拉取历史消息呢?

只须要在客户端本地存储一个上一次拉取到的msg_id(time),到服务端从新拉取便可。

这里还有个问题,因为服务端存储全部消息成本是很是高的,因此通常“消息漫游”是有时间(或者消息数)限制,不能拉取全部全部几年前的历史消息,只能拉取最近的云端消息。
画外音:
你猜,微信有没有存储,几年前的消息呢?
你猜,交一个超级会员费,是否是能够查询呢?


总结

“多点登陆”是指多个端同时登陆一个账号,同时收发消息,关键点是:
(1) 须要在服务端存储同一个用户多个端的状态与登录点;
(2) 发出消息时,要对发送方的多端与接收端的多端,都进行消息投递;

“消息漫游”是指一个用户在任何端,均可以拉取到历史消息,关键点是:
(1) 全部消息存储在云端;
(2) 每一个端本地存储last_msg_id,在登陆时能够到云端同步历史消息;
(3) 云端存储全部消息成本较高,通常会对历史消息时间(或者条数)进行限制;


假如你来实现,你会怎么作?
但愿你们有收获。
微信多点登陆,消息漫游,假如让你来实现?

架构师之路-分享可落地的技术文章

相关推荐:《GFS架构启示》《Google MapReduce解决什么问题?》《Google MapReduce巧妙优化思路?》《Google MapReduce架构设计实践》《MapReduce,颠覆了分层架构的本质?》

相关文章
相关标签/搜索