|
手艺频道
|
51CTO旗下网站
|
|
挪动端
www.9.am

自己动手撸一个分布式IM(即时通讯) 体系

之前分享过一篇《设想一个百万级的新闻推送体系》,固然在文中揭了一些真代码,然则有同伙期望能间接分享一些能够运转的源码,这么暂了是时刻把坑挖上了。

作者:crossoverJie泉源:|2019-03-21 09:45

之前分享过一篇《》,固然在文中揭了一些真代码,然则有同伙期望能间接分享一些能够运转的源码,这么暂了是时刻把坑挖上了。

因而我在之前的基础上完美了一些内容,先来看看这个项目的引见吧:CIM(CROSS-IM) 一款面向开发者的 IM(即时通讯)体系,同时供应了一些组件资助开发者构建一款属于本身可程度扩大的 IM 。

借助 CIM 您能够实现以下需求:

  • IM 即时通讯体系。
  • 适用于 App 的新闻推送中间件。
  • IOT 海量衔接场景中的新闻透传中间件。

完好源码托管在 GitHub :

  1. https://github.com/crossoverJie/cim 

本次重要涉及到 IM 即时通讯,以是专程录了两段视频演示(群聊、私聊)。

群聊

私聊

架构设想

上面来看看详细的架构设想:

  • CIM 中的各个组件均接纳 Spring Boot 构建。
  • 接纳 Netty + Google Protocol Buffer 构建底层通讯。
  • Redis 寄存各个客户端的路由信息、账号信息、在线状况等。
  • Zookeeper 用于 IM-server 服务的注册取发明。

整体重要由以下模块构成:

  • cim-server,IM 服务端:用于吸收 Client 衔接、新闻透传、新闻推送等功用。支撑集群布置。
  • cim-forward-route,新闻路由服务器:用于处置惩罚新闻路由、新闻转发、用户登录、用户下线和一些运营东西(获得在线用户数等)。
  • cim-client,IM 客户端:给用户运用的新闻终端,一个下令便可启动并背其他人提议通信(群聊、私聊);同时内置了一些常用命令轻易运用。

流程图

整体的流程也对照简朴,流程图以下:

  • 客户端背 Route 提议登录。
  • 登录胜利从 Zookeeper 中选择可用 im-server 返回给客户端,并生存登录、路由信息到 Redis。
  • 客户端背 im-server 提议少衔接,胜利后连结心跳。
  • 客户端下线时经由过程 Route 消灭状况信息。

以是当我们本身布置时需求以下步调:

  • 搭建根蒂根基中间件 Redis、Zookeeper。
  • 布置 cim-server,那是真正的 IM 服务器,为了知足机能需求以是支撑程度扩大,只需求注册到同一个 Zookeeper 便可。
  • 布置 cim-forward-route,那是路由服务器,所有的新闻皆需求经由它。因为它是无状况的,以是也能够应用 Nginx 署理进步可用性。
  • cim-client 真正面向用户的客户端;启动以后会主动衔接 IM 服务器便能够在控制台收发新闻了。

更多运用引见能够参考快速启动。

具体设想

接下来重点看看详细的实现,好比群聊、公聊新闻怎样流转;IM 服务端负载平衡;服务怎样注册发明等等。

IM 服务端

先来看看服务端;重要是实现客户端上下线、新闻下发等功用。

起首是服务启动:

由因而在 Spring Boot 中搭建的,以是在运用启动时需求启动 Netty 服务。

从 Pipline 中能够看出运用了 Protobuf 的编解码(详细报文在客户端中剖析)。

注册发明

需求知足 IM 服务端的程度扩大需求,以是 cim-server 是需求将本身数据公布到注册中央的。

以是在运用启动胜利后需求将本身数据注册到 Zookeeper 中。

最主要的目标就是将当前运用的 ip + cim-server-port+ http-port 注册上去。

上图是我在演示情况中注册的两个 cim-server 实例(因为在一台服务器,以是只是端口差别)。

如许在客户端(监听这个 Zookeeper 节点)便能及时的晓得现在可用的服务信息。

登录

当客户端恳求 cim-forward-route 中的登录接口(详见下文)做完业务考证(便相当于一样平常登录其他网站一样)以后,客户端会背服务端提议一个少衔接,如之前的流程所示:

这时候客户端会发送一个特别报文,注解当前是登录信息。服务端收到后便需求将该客户端的 userID 和当前 Channel 通道干系生存起来。

同时也缓存了用户的信息,也就是 userID 和用户名。

离线

当客户端断线后也需求将适才缓存的信息浑撤除。

同时也需求挪用 Route 接口消灭相干信息(详细接口看下文)。

IM 路由

从架构图中能够看出,路由层是非常重要的一环;它供应了一系列的 HTTP 服务承接了客户端和服务端。现在重要是以下几个接口:

①注册接口

因为每个客户端都是需求登录才气运用的,以是第一步天然是注册。

这里便设想的对照简朴,间接应用 Redis 去存储用户信息;用户信息也只要 ID 和 userName 罢了。

只是为了轻易查询在 Redis 中的 KV 又反过来存储了一份 VK,如许 ID 和 userName 皆必需唯一。

②登录接口

这里的登录和 cim-server 中的登录不一样,具有业务性子:

  • 登录胜利以后需求判定是不是是反复登录(一个用户只能运转一个客户端)。
  • 登录胜利后需求从 Zookeeper 中获得服务列表(cim-server)并凭据某种算法选择一台服务返回给客户端。
  • 登录胜利以后借需求生存路由信息,也就是当前用户分派的服务实例生存到 Redis 中。

为了实现只能一个用户登录,运用了 Redis 中的 Set 去生存登录信息;应用 userID 作为 Key ,反复的登录便会写入失利。

类似于 Java 中的 HashSet,只能去重生存。

获得一台可用的路由实例也对照简朴:

  • 先从 Zookeeper 获得所有的服务实例做一个内部缓存。
  • 轮询选择一台服务器(现在只要那一种算法,后续会新增)。

固然要获得 Zookeeper 中的服务实例前,天然是需求监听 cim-server 之前注册上去的谁人节点。

详细代码以下:

也是在运用启动以后监听 Zookeeper 中的路由节点,一旦发作转变便会更新内部缓存。

这里运用的是 Guava 的 Cache,它基于 Concurrent HashMap,以是能够包管消灭、新增缓存的原子性。

③群聊接口

那是一个真正发新闻的接口,实现的结果就是个中一个客户端发新闻,其他所有客户端皆能收到!

流程一定是客户端发送一条新闻到服务端,服务端收到后在上文引见的 SessionSocketHolder 中遍历所有 Channel(通道)然后下发新闻便可。

服务端是单机倒也能够,但如今是集群设想。以是所有的客户端会凭据之前的轮询算法分派到差别的 cim-server 实例中。

因而便需求路由层去发挥作用了:

路由接口收到新闻后起首遍历出所有的客户端和服务实例的干系。路由干系在 Redis 中的寄存以下:

因为 Redis 单线程的特质,当数据量大时;一旦运用 Keys 婚配所有 cim-route:* 数据,会致使 Redis 不克不及处置惩罚其他恳求。

以是这里改为运用 Scan 下令去遍历所有的 cim-route:*。接着会挨个挪用每一个客户端地点的服务端的 HTTP 接口用于推送新闻。

在 cim-server 中的实现以下:

金沙990官方

金沙xpj线路检测

cim-server 收到新闻后会在内部缓存中查询该 userID 的通道,接着只需求发新闻便可。

④在线用户接口

那是一个辅佐接口,能够查询出当前在线用户信息。

实现也很简朴,也就是查询之前生存 ”用户登录状况的谁人去重 set “便可。

⑤公聊接口

之所以道获得在线用户是一个辅佐接口,实在就是用于辅佐公聊运用的。

一样平常我们运用公聊的条件一定得晓得当前哪些用户在线,接着您才会晓得您要和谁停止公聊。

类似于如许:

在我们这个场景中,公聊的条件就是需求得到在线用户的 userID。

以是公聊接口在收到新闻后需求查询到接收者地点的 cim-server 实例信息,后续的步调便和群聊同等了。挪用接收者地点实例的 HTTP 接口下发信息。

只是群聊是遍历所有的在线用户,私聊只发送一个的区分。

⑥下线接口

一旦客户端下线,我们便需求将之前寄存在 Redis 中的一些信息删除失落(路由信息、登录状况)。

IM 客户端

客户端中的一些逻辑其着实上文曾经谈到一些了。

登录

第一步也就是登录,需求在启动时调用 Route 的登录接口,得到 cim-server 信息再创建衔接。

登录历程中 Route 接口会判定是不是为反复登录,反复登录则会间接退出顺序。

接下来是应用 Route 接口返回的 cim-server 实例信息(ip+port)建立衔接。

最初一步就是发送一个登录标记的信息到服务端,让它连结客户端和 Channel 的干系。

自定义和谈

上文提到的一些登录报文、真正的新闻报文这些都是在我们自定义和谈中能够区分出来的。

由因而运用 Google Protocol Buffer 编解码,以是先看看原始花样。

实在这个和谈中现在一共便三个字段:

  • requestId 能够明白为 userId。
  • reqMsg 就是真正的新闻。
  • type 也就是上文提到的新闻种别。

现在重要是三品种型,离别对应差别的业务:

心跳

为了连结客户端和服务端的衔接,每隔一段时间没有发送新闻皆需求主动的发送心跳。

现在的战略是每隔一分钟便发送一个心跳包到服务端:

如许服务端每隔一分钟没有收到业务新闻时就会收到 Ping 的心跳包:

内置下令

客户端也内置了一些根基下令去轻易运用。

好比输入 :q 便会退出客户端,同时会封闭一些系统资源。

当输入 :olu(onlineUser 的简写)就会去挪用 Route 的获得所有在线用户接口。

群聊

群聊的运用异常简朴,只需求在控制台输入新闻回车便可。这时候会去挪用 Route 的群聊接口。

私聊

公聊也是同理,但条件是需求触发关键字;运用 userId;; 新闻内容如许的花样才会给某个用户发送新闻,以是一样平常皆需求先运用 :olu 下令获得所有在线用户才轻易运用。

新闻回调

为了知足一些定制需求,好比新闻需求生存之类的。以是在客户端收到新闻以后会回调一个接口,在这个接口中能够自定义实现。

因而先建立了一个 Caller 的 Bean,这个 Bean 中包含了一个 CustomMsgHandleListener 接口,需求自行处置惩罚只需求实现此接口便可。

自定义界面

因为我本身不怎么会写界面,但保禁绝有其他大牛会写。以是客户端中的群聊、私聊、获得在线用户、新闻回调等业务(和以后的业务)皆是以接口情势供应。

也轻易前面做页面集成,只需求调这些接口便止了;详细实现不消怎样体贴。

总结

Cim 现在只是初版,Bug 多,功用少(只推了几个群友做了测试);不外后续借会接着完美,最少这一版会给那些没有相干履历的同伙带来一些思绪。

后续企图:

【编纂推荐】

【责任编辑:武晓燕 TEL:(010)68476606】

点赞 0
  •     
分享:
人人皆在看
猜您喜好
金沙xpj线路检测

编纂推荐

头条
存眷
热点
聚焦
头条
24H热文
一周话题
本月最赞

定阅专栏

优化运维流水线
共3章 | youerning

143人定阅进修

IT人的职场心法
共22章 | Bear_Boss

73人定阅进修

运维标配手艺
共15章 | one叶孤舟

168人定阅进修

视频课程

讲师:20958人进修过

讲师:193216人进修过

讲师:25955人进修过

CTO品牌
362.com

最新专题

精选博文
论坛热帖
下载排行
金沙xpj线路检测

读 书

本书专门凭据SUN官方的SCSA for Solaris 9&10测验纲目撰写而成,周全掩盖了SCSA for Solaris 9/10的认证考点,除此之外本书另有大量的非考...

定阅51CTO邮刊

51CTO服务号

51CTO播客