作者:yuanrwjuejin.im/post/5d6b3949f265da03c34c13e5前言首先讲讲IM(即时通讯)技术可以用来做什么:谈天:qq、微信直播:斗鱼直播、抖音实时位置共享、游戏多人互动等等可以说险些所有高实时性的应用场景都需要用到IM技术。本篇将带大家从零开始搭建一个轻量级的IM服务端,麻雀虽小,五脏俱全,我们搭建的IM服务端实现以下功效:一对一的文本消息、文件消息通信每个消息有“已发送”/“已送达”/“已读”回执存储离线消息支持用户登录,挚友关系等基本功效。能够利便地水平扩展通过这个项目能学到什么?这个项目涵盖了许多后端必备知识:rpc通信数据库缓存消息行列漫衍式、高并发的架构设计docker部署消息通信文本消息我们先从最简朴的特性开始实现:一个普通消息的发送消息花样如下:message ChatMsg{ id = 1; //消息id fromId = Alice //发送者userId destId = Bob //吸收者userId msgBody = hello //消息体}如上图,我们现在有两个用户:Alice和Bob毗连到了服务器,当Alice发送消息message(hello)给Bob,服务端吸收到消息,凭据消息的destId举行转发,转发给Bob。发送回执那我们要怎么来实现回执的发送呢?我们界说一种回执数据花样ACK,MsgType有三种,划分是sent(已发送),delivered(已送达), read(已读):message AckMsg { id; //消息id fromId; //发送者id destId; //吸收者id msgType; //消息类型 ackMsgId; //确认的消息id}enum MsgType { DELIVERED; READ;}当服务端接受到Alice发来的消息时:1.向Alice发送一个sent(hello)表现消息已经被发送到服务器。
message AckMsg { id = 2; fromId = Alice; destId = Bob; msgType = SENT; ackMsgId = 1;}2.服务器把hello转发给Bob后,连忙向Alice发送delivered(hello)表现消息已经发送给Bob。message AckMsg { id = 3; fromId = Bob; destId = Alice; msgType = DELIVERED; ackMsgId = 1;}3.Bob阅读消息后,客户端向服务器发送read(hello)表现消息已读message AckMsg { id = 4; fromId = Bob; destId = Alice; msgType = READ; ackMsgId = 1;}这个消息会像一个普通谈天消息一样被服务器处置惩罚,最终发送给Alice。
在服务器这里不区分ChatMsg和AckMsg,处置惩罚历程都是一样的:剖析消息的destId并举行转发。水平扩展当用户量越来越大,一定需要增加服务器的数量,用户的毗连被疏散在差别的机械上。此时,就需要存储用户毗连在哪台机械上。
我们引入一个新的模块来治理用户的毗连信息。治理用户状态模块叫做user status,共有三个接口:这样我们就能够对用户毗连状态举行治理了,详细的实现应思量服务的用户量、期望性能等举行实现。此处我们使用redis来实现,将userId和connectorId的关系以key-value的形式存储。
消息转发除此之外,还需要一个模块在差别的机械上转发消息,如下结构:此时我们的服务被拆分成了connector和transfer两个模块,connector模块用于维持用户的长链接,而transfer的作用是将消息在多个connector之间转发。现在Alice和Bob毗连到了两台connector上,那么消息要如何通报呢?1.Alice上线,毗连到机械[1]上时将Alice和它的毗连存入内存中。挪用user status的online方法记载Alice上线。2.Alice发送了一条消息给Bob机械[1]收到消息后,剖析destId,在内存中查找是否有Bob。
如果没有,代表Bob未毗连到这台机械,则转发给transfer。3.transfer挪用user status的getConnectorId(Bob)方法找到Bob所毗连的connector,返回机械[2],则转发给机械[2]。
流程图:总结:引入user status模块治理用户毗连,transfer模块在差别的机械之间转发,使服务可以水平扩展。为了满足实时转发,transfer需要和每台connector机械都保持长链接。离线消息如果用户当前不在线,就必须把消息持久化下来,等候用户下次上线再推送,这里使用mysql存储离线消息。为了利便地水平扩展,我们使用消息行列举行解耦。
transfer吸收到消息后如果发现用户不在线,就发送给消息行列入库。用户登录时,服务器从库里拉取离线消息举行推送。用户登录、挚友关系用户的注册登录、账户治理、挚友关系链等功效更适合使用http协议,因此我们将这个模块做成一个restful服务,对外袒露http接口供客户端挪用。
至此服务端的基本架构就完成了:总结以上就是这篇博客的所有内容,本篇帮大家构建了IM服务端的架构,但另有许多细节需要我们去思考,例如:如何保证消息的顺序和唯一多个设备在线如何保证消息一致性如那边理消息发送失败消息的宁静性如果要存储谈天记载要怎么做数据库分表分库服务高可用……更多细节实现就留到下一篇啦~IM1.0.0版本已上线,github链接:https://github.com/yuanrw/IM。
本文来源:亚博yabo888网页登录-www.xaygl.com