前言

首先讲讲IM(即时通讯)技术可以用来做什么:

  • 聊天:qq、微信

  • 直播:斗鱼直播、抖音

  • 实时位置共享、游戏多人互动等等

可以说几乎所有高实时性的应用场景都需要用到IM技术。

本篇将带大家从零开始搭建一个轻量级的IM服务端,麻雀虽小,五脏俱全,我们搭建的IM服务端实现以下功能:

  • 一对一的文本消息、文件消息通信

  • 每个消息有“已发送”/“已送达”/“已读”回执

  • 存储离线消息

  • 支持用户登录,好友关系等基本功能。

  • 能够方便地水平扩展

通过这个项目能学到什么?

这个项目涵盖了很多后端必备知识:

  • rpc通信

  • 数据库

  • 缓存

  • 消息队列

  • 分布式、高并发的架构设计

  • docker部署

消息通信

文本消息

我们先从最简单的特性开始实现:一个普通消息的发送

消息格式如下:

message ChatMsg{id = 1;//消息idfromId = Alice//发送者userIddestId = Bob//接收者userIdmsgBody = hello//消息体
}

如上图,我们现在有两个用户:Alice和Bob连接到了服务器,当Alice发送消息message(hello)给Bob,服务端接收到消息,根据消息的destId进行转发,转发给Bob。

发送回执

那我们要怎么来实现回执的发送呢?

我们定义一种回执数据格式ACK,MsgType有三种,分别是sent(已发送),delivered(已送达), read(已读):

message AckMsg {id;//消息idfromId;//发送者iddestId;//接收者idmsgType;//消息类型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,共有三个接口:

public interface UserStatusService {/*** 用户上线,存储userId与机器id的关系** @param userId* @param connectorId* @return 如果当前用户在线,则返回他连接的机器id,否则返回null*/String online(String userId, String connectorId);/*** 用户下线** @param userId*/void offline(String userId);/*** 通过用户id查找他当前连接的机器id** @param userId* @return*/String getConnectorId(String userId);
}

这样我们就能够对用户连接状态进行管理了,具体的实现应考虑服务的用户量、期望性能等进行实现。

此处我们使用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

1. SpringBoot内容聚合

2. 面试题内容聚合

3. 设计模式内容聚合

4. Mybatis内容聚合

5. 多线程内容聚合

最后,推荐一个专注于Java学习的公众号,Java知音。分享java基础、原理性知识、JavaWeb实战、spring全家桶、设计模式及面试资料、开源项目,助力开发者成长!

从零开始开发IM(即时通讯)服务端(一)附源码相关推荐

  1. 分享一套开源的即时通讯 IM 聊天系统(附源码)

    大家好,今天推荐一个即时通讯系统项目. 上次是谁要的即时通讯系统项目啊,帮你找到了.这是我目前见过的最好的即时通讯系统项目.功能完整,代码结构清晰.值得推荐.开篇电商平台最不能缺的就是即时通讯,例如通 ...

  2. Android-IM从零开始开发一个即时通讯项目

    Android-IM从零开始开发一个即时通讯项目 https://www.jianshu.com/p/dca480006691 关于聊天室项目 聊天室项目,也被称为即时通讯(IM). 其原理是服务器是 ...

  3. 使用tomcat方式实现websocket即时通讯服务端讲解

    使用tomcat方式实现websocket即时通讯服务端讲解 第一种方案:使用Tomcat的方式实现 tomcat版本要求:tomcat7.0+.需要支持Javaee7 导入javeee-api的ja ...

  4. 基于JAVA融呗智慧金融微资讯移动平台服务端计算机毕业设计源码+数据库+lw文档+系统+部署

    基于JAVA融呗智慧金融微资讯移动平台服务端计算机毕业设计源码+数据库+lw文档+系统+部署 基于JAVA融呗智慧金融微资讯移动平台服务端计算机毕业设计源码+数据库+lw文档+系统+部署 本源码技术栈 ...

  5. 基于JAVA社区养老综合服务平台服务端计算机毕业设计源码+数据库+lw文档+系统+部署

    基于JAVA社区养老综合服务平台服务端计算机毕业设计源码+数据库+lw文档+系统+部署 基于JAVA社区养老综合服务平台服务端计算机毕业设计源码+数据库+lw文档+系统+部署 本源码技术栈: 项目架构 ...

  6. android 原生开发 3d地图 下载_arcgis api 3.x for js 入门开发系列二不同地图服务展示(附源码下载)...

    前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...

  7. java计算机毕业设计高校多媒体设备运维管理系统服务端(附源码、数据库)

    java计算机毕业设计高校多媒体设备运维管理系统服务端(附源码.数据库) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ ...

  8. JAVA计算机毕业设计社区志愿者服务管理系统(附源码、数据库)

    JAVA计算机毕业设计社区志愿者服务管理系统(附源码.数据库) 目运行 环境项配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Eclis ...

  9. java计算机毕业设计桂林餐饮服务平台(附源码、数据库)

    java计算机毕业设计桂林餐饮服务平台(附源码.数据库) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Eclispe( ...

  10. JAVA计算机毕业设计融呗智慧金融微资讯移动平台小程序端(附源码、数据库)

    JAVA计算机毕业设计融呗智慧金融微资讯移动平台小程序端(附源码.数据库) 目运行 环境项配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ ...

最新文章

  1. ThinkPad -- Intel 无线网卡网络连接方法限制及无法用 Fn + F5 控制的问题
  2. 【亲测有效】如何安装屏幕录制工具ScreenPresso
  3. 自由意志不存在?神经科学能证明不?
  4. HTML5 2D平台游戏开发#7Camera
  5. Python使用正则表达式分割字符串
  6. SpringBoot加Jquery实现ajax传递json字符串并回显消息(已实践)
  7. k8s组件说明:ETCD存储组件
  8. 基于netty的微服务架构
  9. java学习(82):静态代码块内部类
  10. python改变turtle画笔方向的函数_哪个选项不能改变turtle画笔的运行方向?
  11. TYPES、DATA、TYPE、LIKE、CONSTANTS、STATICS、TABLES
  12. mysql get global_getdata table表格数据join mysql方法
  13. 如何取得GridView被隐藏列的值
  14. linux入门常用命令
  15. 51单片机全自动锂电池容量电量检测放电电流电压ACS712 ADC0832
  16. 计算机电源维护维修方法,电脑电源维修方法
  17. 模具设计详细流程,建议收藏
  18. 保姆级教程!Windows右下角扬声器有红叉,点击声音设置输出显示“未安装任何音频输出设备”?
  19. html mp4断点播放,html5解决大文件断点续传
  20. 20165309 实验四 Android程序设计

热门文章

  1. Errors were encountered while preparing your device for development. Please check the Devices and Si
  2. Cisco 防火墙Firwall Failover ActiveActive 双HSRP 实现双ISP完美切换
  3. AD18 PCB高亮
  4. 对于大数据、人工智能时代,我们应该如何面对?
  5. Python 为何能坐稳 AI 时代头牌语言
  6. 弘辽科技:成立仅5年的拼多多是如何一步步“紧逼”阿里的?
  7. esp8266保存html文件,八,ESP8266 文件保存数据(示例代码)
  8. “消费者至上:媒体新时代 ”主题响彻IBC2019
  9. 【网络摘录】Google网页搜索技巧
  10. windows10下激活conda环境报错CommandNotFoundError: Your shell has not been properly configured to use conda