乐趣区

关于即时通讯:基于Netty徒手撸IM一IM系统设计篇

本文收作者“大白菜”分享,有改变。留神:本系列是给 IM 初学者的文章,IM 老油条们还望海涵,勿喷!

1、引言

这又是一篇基于 Netty 的 IM 编码实际文章,因为合成一篇内容太长,读起来太累,所以也就顺着作者的思路离开成 4 篇,读起来心理压力也就没那么大了。

这个系列的几篇文章分享的是:假如在没有任何成型的第 3 方 IM 库或 SDK 的状况下,以网络编程的根底技术视线,思考和实际如何基于 Netty 网络库从零写一个能够聊天的 IM 零碎的过程,没有目迷五色的架构设计、也没有高端大气的模式设计方法论,有的只是从 IM 入门者的角度的思路和实战,适宜 IM 初学者浏览。

本篇次要是徒手撸 IM 系列的开篇,次要解说的是的 IM 设计思路,不波及实际编码,心愿给你带来帮忙。

学习交换:

  • 挪动端 IM 开发入门文章:《新手入门一篇就够:从零开发挪动端 IM》
  • 开源 IM 框架源码:https://github.com/JackJiang2…(备用地址点此)

(本文已同步公布于:http://www.52im.net/thread-39…)

2、常识筹备

  • 重要提醒:本系列文章次要是代码实战分享,如果你对即时通讯(IM)技术实践理解的不多,倡议先具体浏览:《零根底 IM 开发入门:什么是 IM 零碎?》、《新手入门一篇就够:从零开发挪动端 IM》。

不晓得 Netty 是什么?这里简略介绍下:

Netty 是一个 Java 开源框架。Netty 提供异步的、事件驱动的网络应用程序框架和工具,用以疾速开发高性能、高可靠性的网络服务器和客户端程序。

也就是说,Netty 是一个基于 NIO 的客户、服务器端编程框架,应用 Netty 能够确保你疾速和简略的开发出一个网络应用,例如实现了某种协定的客户,服务端利用。

Netty 相当简化和流线化了网络应用的编程开发过程,例如,TCP 和 UDP 的 Socket 服务开发。

Netty 的根底入门好文章:

1)新手入门:目前为止最透彻的的 Netty 高性能原理和框架架构解析
2)写给初学者:Java 高性能 NIO 框架 Netty 的学习办法和进阶策略
3)史上最艰深 Netty 框架入门长文:根本介绍、环境搭建、入手实战

如果你连 Java 的 NIO 都不晓得是什么,上面的文章倡议优先读:

1)少啰嗦!一分钟带你读懂 Java 的 NIO 和经典 IO 的区别
2)史上最强 Java NIO 入门:放心从入门到放弃的,请读这篇!
3)Java 的 BIO 和 NIO 很难懂?用代码实际给你看,再不懂我转行!

Netty 源码和 API 的在线查阅地址:

1)Netty-4.1.x 残缺源码(在线浏览版)(* 举荐)
2)Netty-4.1.x API 文档(在线版)

3、系列文章

本文是系列文章的第 1 篇,以下是系列目录:

《基于 Netty,徒手撸 IM(一):IM 零碎设计篇》(* 本文)
《基于 Netty,徒手撸 IM(二):编码实际篇(单聊性能)》
《基于 Netty,徒手撸 IM(三):编码实际篇(群聊性能)》
《基于 Netty,徒手撸 IM(一):编码实际篇(系统优化)》

4、需要剖析

业务场景:本次实战就是模仿微信的 IM 聊天,每个客户端和服务端建设连贯,并且能够实现点对点通信(单聊),点对多点通信(群聊)。

设计思路:咱们要实现的是点(客户端)对点(客户端)的通信,然而咱们大部分状况下接触的业务都是客户端和服务端之间的通信(所谓的 C / S 模式?),客户端只须要晓得服务端的 IP 地址和端口号即可发动通信了。那么客户端和客户端应该怎么去设计呢?

技术思考:难道是手机和手机之间建设通信连贯(所谓的 P2P),相互发送音讯吗?

这种计划显然不是很好的计划:

1)首先:客户端和客户端之间通信,首先须要确定对方的 IP 地址和端口号,显然不是很事实;
2)其次:即便有方法拿到对方的 IP 地址和端口号,那么每个点(客户端)既作为服务端还得作为客户端,无形之中减少了客户端的压力。

其实:咱们能够应用服务端作为 IM 聊天音讯的中转站,由服务端被动往指定客户端推送音讯。如果是这种模式的话,那么 Http 协定是无奈反对的(因为 Http 是无状态的,只能一申请一响应的模式),于是就只能应用 TCP 协定去实现了。

Jack Jiang 注:此处作者表述不太精确,因为尽管 HTTP 是无状态的,但一样能够实现即时通讯能力,有趣味的读者能够浏览以下几篇文章,理解一下这些已经利用 HTTP 实现即时通讯聊天的技术办法:

《新手入门贴:史上最全 Web 端即时通讯技术原理详解》
《Web 端即时通讯技术盘点:短轮询、Comet、Websocket、SSE》
《网页端 IM 通信技术疾速入门:短轮询、长轮询、SSE、WebSocket》

5、IM 单聊思路设计

5.1 通信架构原理
以下是通信架构原理图:

如上图所示,通信流程解析如下:

1)实现客户端和客户端之间通信,那么须要应用服务端作为通信的中转站,每个客户端都必须和服务端建设连贯;
2)每个客户端和服务端建设连贯之后,服务端保留用户 ID 和通道的映射关系,其中用户 ID 作为客户端的惟一标识;
3)客户端 A 往客户端 B 发送音讯时,先把音讯发送到服务端,再有服务端往客户端 B 进行推送。

针对上述第“3)”点,服务端如何找到客户端 B 呢?

客户端 A 往服务端发送音讯时,音讯携带的信息有:“客户端 A 用户 ID”、“客户端 B 用户 ID”、“音讯内容”。这样服务端就能顺利找到服务端 B 的通道并且进行推送音讯了。

5.2 音讯推送流程
每个客户端和服务端建设连贯的时候,必须把个人用户信息上传到服务端,由服务端对立保留映射关系。如果某个客户端下线了,则服务端监听到连贯断开,删除对应的映射关系。

其次:发动群聊的时候,须要传递 touser 字段,服务端依据该字段在映射表外面查找到对应的连贯通道并发动音讯推送。

上述逻辑原理如下图所示:

5.3 更多的细节
其实在真正要做 IM 之前,要思考的技术细节还是很多的,以下这几篇文章就步及到了典型的几个 IM 热门技术点,有趣味的肯定要读一读:

《挪动端 IM 开发须要面对的技术问题》
《谈谈挪动端 IM 开发中登录申请的优化》
《IM 音讯送达保障机制实现(一):保障在线实时音讯的牢靠投递》
《IM 音讯送达保障机制实现(二):保障离线音讯的牢靠投递》
《如何保障 IM 实时音讯的“时序性”与“一致性”?》

6、IM 群聊思路设计

群聊指的是一个组内多个用户之间的聊天,一个用户发到群组的音讯会被组内任何一个成员接管。

具体架构思路如下所示:

如上图所示,群聊通信流程解析如下。

1)群聊其实和单聊整体上思路都是统一的,都是须要保留每个用户和通道的对应关系,不便前期通过用户 ID 去查找到对应的通道,再跟进通道推送音讯。

2)如何把音讯发送给多个组内的成员呢?

其实很简略,服务端再保留另外一份映射关系,那就是聊天室和成员的映射关系。发送音讯时,首先依据聊天室 ID 找到对应的所有成员,而后再跟进各个成员的 ID 去查找到对应的通道,最初由每个通道进行音讯的发送。

3)成员退出某个群聊组的时候,往映射表新增一条记录,如果成员退群的时候则删除对应的映射记录。

通过下面的架构图能够发现,群聊和单聊相比,其实就是多了一份映射关系而已。

其实群聊是 IM 里相对来说技术难度较高的性能,有趣味的读者能够浏览上面这几篇:

《IM 单聊和群聊中的在线状态同步应该用“推”还是“拉”?》
《IM 群聊音讯如此简单,如何保障不丢不重?》
《挪动端 IM 中大规模群音讯的推送如何保障效率、实时性?》
《古代 IM 零碎中聊天音讯的同步和存储计划探讨》
《对于 IM 即时通讯群聊音讯的乱序问题探讨》
《IM 群聊音讯的已读回执性能该怎么实现?》
《IM 群聊音讯到底是存 1 份 (即扩散读) 还是存多份(即扩散写)?》
《一套高可用、易伸缩、高并发的 IM 群聊、单聊架构方案设计实际》

另外,对于超大规模群聊,技术难度更是指数回升:

《网易云信技术分享:IM 中的万人群聊技术计划实际总结》
《阿里钉钉技术分享:企业级 IM 王者——钉钉在后端架构上的过人之处》
《IM 群聊音讯的已读未读性能在存储空间方面的实现思路探讨》
《企业微信的 IM 架构设计揭秘:音讯模型、万人群、已读回执、音讯撤回等》
《融云 IM 技术分享:万人群聊音讯投递计划的思考和实际》
《微信直播聊天室单房间 1500 万在线的音讯架构演进之路》

7、本文小结

本篇次要是帮忙读者把握单聊和群聊的外围设计思路。

单聊:次要是服务器保留了一份用户和通道之间的映射关系,发送音讯的时候,依据接管人 ID 找到其对应的通道 Channel,Channel 的 write () 能够给客户端发送音讯。

群聊:保留两份关系,别离是用户 ID 和 Channel 之间的关系、群组 ID 和用户 ID 的关系。推送音讯的时候,首先依据聊天组 ID 找到其对应的成员,遍历每个成员再进行找出其对应的通道即可。

整体来说,思路还是很简略的,把握了该设计思路当前,你会发现设计一款 IM 聊天软件其实也不是很简单。

8、相干文章

如果你感觉对本系列文章还不够具体,能够零碎学习以下系列文章:

《跟着源码学 IM(一):手把手教你用 Netty 实现心跳机制、断线重连机制》
《跟着源码学 IM(二):自已开发 IM 很难?手把手教你撸一个 Andriod 版 IM》
《跟着源码学 IM(三):基于 Netty,从零开发一个 IM 服务端》
《跟着源码学 IM(四):拿起键盘就是干,教你徒手开发一套分布式 IM 零碎》
《跟着源码学 IM(五):正确理解 IM 长连贯、心跳及重连机制,并入手实现》
《跟着源码学 IM(六):手把手教你用 Go 疾速搭建高性能、可扩大的 IM 零碎》
《跟着源码学 IM(七):手把手教你用 WebSocket 打造 Web 端 IM 聊天》
《跟着源码学 IM(八):万字长文,手把手教你用 Netty 打造 IM 聊天》
《跟着源码学 IM(九):基于 Netty 实现一套分布式 IM 零碎》
《跟着源码学 IM(十):基于 Netty,搭建高性能 IM 集群(含技术思路 + 源码)》
《SpringBoot 集成开源 IM 框架 MobileIMSDK,实现即时通讯 IM 聊天性能》

9、参考资料

[1] 新手入门:目前为止最透彻的的 Netty 高性能原理和框架架构解析
[2] 实践联系实际:一套典型的 IM 通信协议设计详解
[3] 浅谈 IM 零碎的架构设计
[4] 简述挪动端 IM 开发的那些坑:架构设计、通信协议和客户端
[5] 一套海量在线用户的挪动端 IM 架构设计实际分享(含具体图文)
[6] 一套原创分布式即时通讯(IM) 零碎实践架构计划
[7] 一套高可用、易伸缩、高并发的 IM 群聊、单聊架构方案设计实际
[8] 一套亿级用户的 IM 架构技术干货(上篇):整体架构、服务拆分等
[9] 一套亿级用户的 IM 架构技术干货(下篇):可靠性、有序性、弱网优化等
[10] 从老手到专家:如何设计一套亿级音讯量的分布式 IM 零碎
[11] 基于实际:一套百万音讯量小规模 IM 零碎技术要点总结
[12] 探探的 IM 长连贯技术实际:技术选型、架构设计、性能优化

(本文已同步公布于:http://www.52im.net/thread-39…)

退出移动版