即时通讯应用服务,整套包含服务端、管理端和客户端
预计3篇分享:这次是第一篇,项目的整体介绍和实体关系的梳理
现已部署上线,客户端和管理端,欢迎体验
可以注册客户端账号,也可以使用初始默认账号,现有初始账号说明:
账号 | 密码 | 说明 |
---|---|---|
admin | 123456 | 管理端账号 |
user | 123456 | 客户端普通用户账号 |
muteuser | 123456 | 客户端被禁言用户账号 |
disabled | 123456 | 客户端被封禁用户账号 |
member1 | 123456 | 客户端普通用户账号 |
member2 | 123456 | 客户端普通用户账号 |
... | 123456 | 客户端普通用户账号 |
member30 | 123456 | 客户端普通用户账号 |
<img width="300" src="https://i.loli.net/2020/07/15/fO2naUmPluYRsBd.png">
移动互联网发展至今,以微信为首的即时通讯服务已经融入了我们生活中的各个角落,在公司的一些业务中也扮演着重要的角色,对于即时通讯我们公司原来是使用的环信的服务,但是有很多定制化的需求无法实现,所以后来决定内部开发一个满足定制化需求的即时通讯微服务。
使用socket.io
框架是因为当时后端缺人,加上看了一些例子后觉得使用起来真的很方便,而且全平台支持,所以这个微服务就在前端团队进行落地实践,目前效果还不错。
社区目前这方面的内容比较少或者太简陋(只有一个公共的聊天室这种)。另外就是在业务开发过程中被 PM 搞得很难受,所以想脱离一些特有的业务上的东西,实现一个功能简单五脏俱全的不掺杂公司业务的 IM 应用,包含服务端,管理端和客户端。客户端的模仿对象是微信,因为我很熟悉,不用在产品上面思考太多,另外就是试用的人很熟悉,不需要太多的沟通成本。
要开发一套完整的即时通讯服务,需要以下部分:
为企业级框架和应用而生
选用阿里的 egg.js 框架做支撑,看中的原因是他们内部大规模的落地和安全方面做得比较好,没有选择 nest 的原因是集成 socket.io
比较麻烦,ORM 选用 sequelize,数据库是 mysql ,之前一起使用过,上手难度小
开箱即用的中台前端/设计解决方案
选择 Ant Design Pro 作为模板开发管理端,选用的原因是我对 Vue 全家桶比较熟悉,想借着这个机会熟悉下整套 React 生态 的开发流程,感受下目前国内两大开发框架的本质区别和殊途同归,Ant Design Pro 已经发布了好几年了,也的确给中小型企业带来效率的提升,也正好适合我这的需求。
🛠️ Vue.js 开发的标准工具
使用 @vue/cli 搭建 IM 服务的客户端,一个移动端的 H5 项目,UI 框架使用的有赞 vant,集成了我的开源组件vue-page-stack和黄老师的better-scroll,实现 IM 的基础功能
作为一个前端工程师,大多数的日常工作是不需要思考实体关系的。但是,就我的实际体验来看,懂得实体关系可以帮助我们更好的理解业务模型。而对产品和业务理解的提升对我们的帮助是非常大的,可以在需求评审的时候发现很多不符合逻辑的地方(怎么又要吐槽产品经理了),这时候能提出来就会主动避免我们在后续的过程中进行反复开发,同时可以和产品侧的同学形成比较良好的互动(而不是互怼)。下面简单罗列下比较重要的实体关系:
<img width="600" src="https://i.loli.net/2020/07/14/Zhz85V2ptOylDcj.png">
通过上图可以看到 user 是整个关系图中的核心,下面介绍下各个实体之间的关系:
下面详细介绍下会话、角色与权限:
完成一个即时通讯应用,需要考虑的第一个事情就是会话,就是我们微信里面的对话窗口。思考会话和消息、用户、群组之间的关系花费了不少的精力,最终形成以下的基本关系:
也就是说,用户和会话没有直接的关系,只能通过用户对应的单聊和群聊去获取会话,这样做可以有以下的好处:
为了设计一个灵活、通用、方便的权限管理系统,本系统采用 RBAC(基于角色的访问控制)控制,来设计一个通用的『用户角色权限』平台,方便后期扩展。
RBAC(基于角色的访问控制)是指用户通过角色与权限进行关联。即一个用户拥有若干角色,每一个角色拥有若干权限(当然了,别把冲突的角色和权限配在一起)。这样,就构造成“用户—角色—权限”的授权模型。在这种模型中,用户与角色之间、角色与权限之间,一般是多对多的关系。
本系统默认有管理员、一般用户、禁言用户和封禁用户这几种角色,给不同的角色分配不同的权限,所以需要针对管理和发言等接口路由做一下统一的鉴权(通过中间件的方式)处理,具体方式和方法在后端项目中会详细说明。本系统暂时采用预先定义了角色和权限的方式,后续想要扩展的话可以编辑角色和权限。
没见过微信的管理端,但是可以想象一下,管理员可以配置用户的角色和权限,可以编辑群组的状态:
注册登录后,可以正常的添加好友和加入群组,可以修改个人基础信息和处理申请
无法登录
举个例子:现在有一个新版的个人中心需要上线测试,首先新建一个角色『测试个人中心』,再给这个角色分配对应的权限;然后给普通用户做个分组,选出一些人配置上这个角色,这样就可以进行测试了。
下面说下即时通讯服务的核心通讯原理,和一般的 http 服务一样,有一个服务端和客户端进行通讯,只不过详细的协议和处理方式不一样。
由于历史原因,现在主流的 http 协议是无状态协议(HTTP2 暂时应用不广泛),一般情况是由客户端主动发起请求,然后服务端去响应。那么为了实现服务端向客户端推送信息,就需要前端主动向后端去轮询,这种方式低效且容易出错,在之前我们的管理端首页确实是这么做的(5s 一次)。
为了实现这种服务端主动推送信息的需求, HTML5 开始提供一种在单个 TCP 连接上进行全双工通讯的协议,也就是 WebSocket。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。WebSocket 协议在 2008 年诞生,2011 年成为国际标准,目前绝大部分浏览器都已经支持了。
WebSocket 的用法相当简单:
var ws = new WebSocket("wss://echo.websocket.org"); ws.onopen = function(evt) { console.log("Connection open ..."); ws.send("Hello WebSockets!"); }; ws.onmessage = function(evt) { console.log( "Received Message: " + evt.data); ws.close(); }; ws.onclose = function(evt) { console.log("Connection closed."); };
有了 WebSocket 协议让服务端主动推送信息有了先进的武器,那么有没有什么方式可以兼容新旧浏览器呢?其实很多人想到了这点,答案就是socket.io
socket.io
socket.io
进一步封装了WebSocket
的接口,而且可以在旧版本浏览器中自主切换到使用轮询的方式进行通讯(我们使用者是不会感知的),形成了一套统一的接口,大大减轻了开发的负担。主要具有以下优点:
这是 socket.io 主页
最快,最可靠的即时通讯引擎(FEATURING THE FASTEST AND MOST RELIABLE REAL-TIME ENGINE)
使用起来真的很简单:
var io = require('socket.io')(80); var cfg = require('./config.json'); var tw = require('node-tweet-stream')(cfg); tw.track('socket.io'); tw.track('javascript'); tw.on('tweet', function(tweet){ io.emit('tweet', tweet); });
有了以上的基础,我们就基本完成了开始写代码之前的准备:明确了这个应用的基础功能和实体之间的关系,也明确了基础的技术方案选型,划分了3个项目的各自任务。下面就开始完成 server 端吧
未完待续:下一篇介绍 server 端