默认
打赏 发表评论 25
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
浅谈IM系统的架构设计
阅读(367416) | 评论(25 收藏28 淘帖1 6
微信扫一扫关注!

1、前言


除去QQ、微信这样的即时通讯聊天工具,还有许多细分行业的IM,比如淘宝阿里旺旺、网易泡泡、YY语音......。恰巧公司产品也要开发一款基于我们自己行业的类IM系统,很有幸我担当了这个产品的架构师,核心代码编写、实现者。下面把我近年来从技术上我对IM系统(即时消息的传输,不包括语音,视频,文件的传输)的理解和设计分享出来,浅薄之见,望大家别见笑,欢迎给出批评意见。

另外,以下几篇有关IM实际动手开发的文章也值得一读,有兴趣可以看看:


2、选择困难症1:网络传输协议的选择


目前我知晓的所有IM系统传输即时消息无外乎使用UDP、TCP、基于TCP的http这几种协议中的一种或几种。比如QQ主要采用UDP协议,MSN主要采用TCP协议,而且他们也都支持HTTP协议的代理模式。更多资料,请参加这篇文章《即时通讯等通信软件的网络协议和端口收集整理》。

我们该如何选择呢?

  • UDP协议实时性更好,但是如何处理安全可靠的传输并且处理不同客户端之间的消息交互是个难题,实现起来过于复杂;
  • HTTP协议属于扩展支持,我们在产品的初始阶段可以不用支持;
  • 那就非TCP协议莫属了,要考虑的同样也有很多,特别是如果有海量用户的需求。如何保证单机服务器高并发量,如何做到灵活,扩展的架构。

(即时通讯网注:还可参考相关文章为什么QQ用的是UDP协议而不是TCP协议?》、《移动端即时通讯协议选择:UDP还是TCP?,更多类似文章:http://www.52im.net/forum.php?mod=collection&action=view&ctid=18。)

3、择困难症2:数据通信格式(协议)的选择


二进制格式?文本格式?这个话题转到这篇文章《如何选择即时通讯应用的数据传输格式》,从我们当前的需求和产品周期上我觉得选择JSON形式的数据协议是最好的。

(即时通讯网注:IM的数据传输格式的选择是个头疼的问题,比如这篇文章跟本文的意见相左强列建议将Protobuf作为你的即时通讯应用数据传输格式,更多类似文章:http://www.52im.net/forum.php?mod=collection&action=view&ctid=18

4、架构设计


首先我们来提炼一下一个IM系统的主要需求,包括账号,关系链,在线状态显示,消息交互......。

4.1架构考量


  • 由于采用可靠传输协议TCP,考虑到负载问题(短连接实现账号、关系链相关业务,长连接实现上线、信息推送);
  • 后台架构的灵活性、可扩展性,支持分布式部署——把网络层、业务逻辑层、数据层分离,网络层和业务层支持负载均衡策略、数据层支持分布式存储;
  • 客户端SDK的易用性:把网络层、数据层分离、业务逻辑层分离。

后台架构简化图:
浅谈IM系统的架构设计_QQ20160514-2.png

架构示意图:
浅谈IM系统的架构设计_QQ20160514-3.png

架构细化图:
浅谈IM系统的架构设计_QQ20160514-4.png

说明:
从架构细化图中可以看出对于上线服务由于建立的是TCP长连接,对于单台服务器往往由于硬件资源、系统资源、网络资源的限制无法做到海量用户的同时 在线,所以设计为根据服务器负载支持多服务器上线,同时由于多服务器上线造成了对整个系统交互(不同的客户端的交互,协作部门应用服务和客户的交互)的分 割,引入消息转发服务器作为粘合点。另外对于多服务器上线造成的统一账户信息(在线状态,消息)数据的分割,引入统一的数据层(内存存储 层:session、状态信息存储、消息队列存储;数据库:账号信息存储)做到业务和数据的分离,也就做到了支持分布式部署。参见我的这篇文章《构建高性能服务的考量》。

对于部分业务服务:做到网络层、业务层、数据层的完全分离。首先对于TCP短连接来说不会如长连接那般消耗资源,即使后期遇到海量的并发访问请求依然可以从容的通过负载均衡策略和数据分布式部署策略进行解决。参见我的这篇文章《服务端架构中的“网关服务器”》。

4.2服务端平台及技术选型


  • 系统开发平台:
    CentOS——Linux发行版的一种,稳定可靠、可定制优化、支持丰富。
  • 网络支撑层:
    libevent——减小开发成本,增强稳定性。
  • 缓存存储层:
    Redis——支持丰富的存储结构,支持分布式存储。
  • 数据库:
    MySQL——最适合互联网的数据库,免授权、高效稳定、可控性高。
  • 开发语言:
    C/C++。

4.3部分热点问题考量


主要是有关系统性能方面的考量:

  • 编码角度:
    采用高效的网络模型,线程模型,I/O处理模型,合理的数据库设计和操作语句的优化;
  • 垂直扩展:
    通过提高单服务器的硬件资源或者网络资源来提高性能;
  • 水平扩展:
    通过合理的架构设计和运维方面的负载均衡策略将负载分担,有效提高性能;后期甚至可以考虑加入数据缓存层,突破IO瓶颈;
  • 系统的高可用性:
    防止单点故障;
  • 在架构设计时做到业务处理和数据的分离,从而依赖分布式的部署使得在单点故障时能保证系统可用。
  • 对于关键独立节点可以采用双机热备技术进行切换。
  • 数据库数据的安全性可以通过磁盘阵列的冗余配置和主备数据库来解决。

4.4主要学习资料


1.4亿在线背后的故事
微信之道-至简

附录:全站即时通讯技术资料分类


[1] 网络编程基础资料:
TCP/IP详解 - 第11章·UDP:用户数据报协议
TCP/IP详解 - 第17章·TCP:传输控制协议
TCP/IP详解 - 第18章·TCP连接的建立与终止
TCP/IP详解 - 第21章·TCP的超时与重传
理论经典:TCP协议的3次握手与4次挥手过程详解
理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程
计算机网络通讯协议关系图(中文珍藏版)
NAT详解:基本原理、穿越技术(P2P打洞)、端口老化等
UDP中一个包的大小最大能多大?
Java新一代网络编程模型AIO原理及Linux系统AIO介绍
NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战
NIO框架入门(四):Android与MINA2、Netty4的跨平台UDP双向通信实战
>> 更多同类文章 ……

[2] 有关IM/推送的通信格式、协议的选择:
为什么QQ用的是UDP协议而不是TCP协议?
移动端即时通讯协议选择:UDP还是TCP?
如何选择即时通讯应用的数据传输格式
强列建议将Protobuf作为你的即时通讯应用数据传输格式
移动端IM开发需要面对的技术问题(含通信协议选择)
简述移动端IM开发的那些坑:架构设计、通信协议和客户端
理论联系实际:一套典型的IM通信协议设计详解
58到家实时消息系统的协议设计等技术实践分享
>> 更多同类文章 ……

[3] 有关IM/推送的心跳保活处理:
Android进程保活详解:一篇文章解决你的所有疑问
Android端消息推送总结:实现原理、心跳保活、遇到的问题等
为何基于TCP协议的移动端IM仍然需要心跳保活机制?
微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)
微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)
移动端IM实践:实现Android版微信的智能心跳机制
移动端IM实践:WhatsApp、Line、微信的心跳策略分析
>> 更多同类文章 ……

[4] 有关WEB端即时通讯开发:
新手入门贴:史上最全Web端即时通讯技术原理详解
Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE
SSE技术详解:一种全新的HTML5服务器推送事件技术
Comet技术详解:基于HTTP长连接的Web端实时通信技术
WebSocket详解(一):初步认识WebSocket技术
socket.io实现消息推送的一点实践及思路
>> 更多同类文章 ……

[5] 有关IM架构设计:
浅谈IM系统的架构设计
简述移动端IM开发的那些坑:架构设计、通信协议和客户端
一套原创分布式即时通讯(IM)系统理论架构方案
从零到卓越:京东客服即时通讯系统的技术架构演进历程
蘑菇街即时通讯/IM服务器开发之架构选择
腾讯QQ1.4亿在线用户的技术挑战和架构演进之路PPT
微信技术总监谈架构:微信之道——大道至简(演讲全文)
如何解读《微信技术总监谈架构:微信之道——大道至简》
快速裂变:见证微信强大后台架构从0到1的演进历程(一)
17年的实践:腾讯海量产品的技术方法论
>> 更多同类文章 ……

[6] 有关IM安全的文章:
即时通讯安全篇(一):正确地理解和使用Android端加密算法
即时通讯安全篇(二):探讨组合加密算法在IM中的应用
即时通讯安全篇(三):常用加解密算法与通讯安全讲解
即时通讯安全篇(四):实例分析Android中密钥硬编码的风险
传输层安全协议SSL/TLS的Java平台实现简介和Demo演示
理论联系实际:一套典型的IM通信协议设计详解(含安全层设计)
微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解
来自阿里OpenIM:打造安全可靠即时通讯服务的技术实践分享
>> 更多同类文章 ……

[7] 有关实时音视频开发:
即时通讯音视频开发(一):视频编解码之理论概述
即时通讯音视频开发(二):视频编解码之数字视频介绍
即时通讯音视频开发(三):视频编解码之编码基础
即时通讯音视频开发(四):视频编解码之预测技术介绍
即时通讯音视频开发(五):认识主流视频编码技术H.264
即时通讯音视频开发(六):如何开始音频编解码技术的学习
即时通讯音视频开发(七):音频基础及编码原理入门
即时通讯音视频开发(八):常见的实时语音通讯编码标准
即时通讯音视频开发(九):实时语音通讯的回音及回音消除概述
即时通讯音视频开发(十):实时语音通讯的回音消除技术详解
即时通讯音视频开发(十一):实时语音通讯丢包补偿技术详解
即时通讯音视频开发(十二):多人实时音视频聊天架构探讨
即时通讯音视频开发(十三):实时视频编码H.264的特点与优势
即时通讯音视频开发(十四):实时音视频数据传输协议介绍
即时通讯音视频开发(十五):聊聊P2P与实时音视频的应用情况
即时通讯音视频开发(十六):移动端实时音视频开发的几个建议
即时通讯音视频开发(十七):视频编码H.264、V8的前世今生
简述开源实时音视频技术WebRTC的优缺点
良心分享:WebRTC 零基础开发者教程(中文)
>> 更多同类文章 ……

[8] IM开发综合文章:
移动端IM开发需要面对的技术问题
开发IM是自己设计协议用字节流好还是字符流好?
请问有人知道语音留言聊天的主流实现方式吗?
IM系统中如何保证消息的可靠投递(即QoS机制)
谈谈移动端 IM 开发中登录请求的优化
完全自已开发的IM该如何设计“失败重试”机制?
微信对网络影响的技术试验及分析(论文全文)
即时通讯系统的原理、技术和应用(技术论文)
开源IM工程“蘑菇街TeamTalk”的现状:一场有始无终的开源秀
>> 更多同类文章 ……

[9] 开源移动端IM技术框架资料:
开源移动端IM技术框架MobileIMSDK:快速入门
开源移动端IM技术框架MobileIMSDK:常见问题解答
开源移动端IM技术框架MobileIMSDK:压力测试报告
开源移动端IM技术框架MobileIMSDK:Android版Demo使用帮助
开源移动端IM技术框架MobileIMSDK:Java版Demo使用帮助
开源移动端IM技术框架MobileIMSDK:iOS版Demo使用帮助
开源移动端IM技术框架MobileIMSDK:Android客户端开发指南
开源移动端IM技术框架MobileIMSDK:Java客户端开发指南
开源移动端IM技术框架MobileIMSDK:iOS客户端开发指南
开源移动端IM技术框架MobileIMSDK:Server端开发指南
>> 更多同类文章 ……

[10] 有关推送技术的文章:
iOS的推送服务APNs详解:设计思路、技术原理及缺陷等
Android端消息推送总结:实现原理、心跳保活、遇到的问题等
扫盲贴:认识MQTT通信协议
一个基于MQTT通信协议的完整Android推送Demo
求教android消息推送:GCM、XMPP、MQTT三种方案的优劣
移动端实时消息推送技术浅析
扫盲贴:浅谈iOS和Android后台实时消息推送的原理和区别
绝对干货:基于Netty实现海量接入的推送服务技术要点
移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)
为何微信、QQ这样的IM工具不使用GCM服务推送消息?
>> 更多同类文章 ……

[11] 更多即时通讯技术好文分类:
http://www.52im.net/forum.php?mod=collection&op=all

(原文链接:http://mobile.51cto.com/hot-439693.htm

即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

上一篇:IM消息送达保证机制实现(一):保证在线实时消息的可靠投递下一篇:微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解

本帖已收录至以下技术专辑

推荐方案
评论 25
学习中
加油咯⛽️
能说说MQ在IM架构中的使用方式么
大家都在做IM服务吗
签名: 该会员没有填写今日想说内容.
学习中
签名:
来学习一下!
签名: 开开开心
慢慢看
签名: 签个到都要吐槽的吗
xuexile
架构很好,可是具体实现好难啊,没有一定积累很难产品化
学习
引用:pigo残 发表于 2017-07-27 10:28
能说说MQ在IM架构中的使用方式么

按照我的理解就是:一般的TCP/IP通信可能出现丢包,也不一定能保证消息顺序发送,MQ就是解决这个问题的。不知道对不对。
博主好,如你所说,将未成功发送的消息或离线消息暂存到消息队列。
1、此时客户端上线,而服务端有在线消息和离线消息都要推给客户端,如何保证这两种消息的时序性?
2、服务端如何判断消息送达,判断客户端是否在线不能保证消息必达;如果用回调+延时判断转发失败,那是不是要用一个队列来管理回调函数?这样在高并发的情况下是否会对系统性能产生影响?
引用:ichampion 发表于 2018-02-01 16:09
博主好,如你所说,将未成功发送的消息或离线消息暂存到消息队列。
1、此时客户端上线,而服务端有在线消 ...

有个概念你可能分的不清。
现在主流的IM中,离线消息和实时消息走的是不同的通道,离线消息是在登陆时通过http短连接“拉”过来的(这种体验你可以在你换手机时,微信首次登陆时,你能看到消息或数据的加载有个加载百分比的显示,能明显感觉出来。平时你如果有群的话,你启动app时会看到未读数一直在往上加,这表示微信在分页加载这些数据,但肯定不会是通过实时通道“推”,真如你所考虑的——这太奢侈了,而且性能一定会有影响)。

你可以参考一下论坛的IM干货系列文章:
引用:JackJiang 发表于 2018-02-01 17:37
有个概念你可能分的不清。
现在主流的IM中,离线消息和实时消息走的是不同的通道,离线消息是在登陆时通 ...

我知道是“拉”取消息,我的意思是:打个比方,我微信上线了,这时候我会从服务端获取离线消息(比如是我朋友约我星期六玩),但是很巧的是,在我拉取消息的时候,这个朋友想确认一下我星期六是否有空,又给我发了信息,此时我是在线的,应该由服务端push过来。那客户端是不是要做消息时间的判断来显示消息呢?否则的话,可能他实时的消息显示在前,离线的消息显示在后。但是客户端做时间判断的话,可能出现一种情况就是我实时的消息显示了,结果离线消息过来以后,在当前的消息之前又冒出来几条消息。这样的场景在微信中好像不存在。
引用:ichampion 发表于 2018-02-02 09:08
我知道是“拉”取消息,我的意思是:打个比方,我微信上线了,这时候我会从服务端获取离线消息(比如是我 ...

离线消息一定是无条件插到聊天列表的前面的,因为这次拉的消息肯定比你刚才收到的实时消息要老,不用判断时间都可以做到。
引用:JackJiang 发表于 2018-02-02 10:40
离线消息一定是无条件插到聊天列表的前面的,因为这次拉的消息肯定比你刚才收到的实时消息要老,不用判断 ...

我就卡在这一步,离线消息如何无条件插到列表前面?如果我的离线消息里面有一张图片(或者说离线消息体量比较大),那这个时候,实时的消息已经push过来了,之后我收到了图片并且转码完成要显示了,如您所说,不判断时间的话,怎么让图片显示在它该显示的地方呢?
学习学习了
良心教程,学习下
引用:ichampion 发表于 2018-02-02 10:50
我就卡在这一步,离线消息如何无条件插到列表前面?如果我的离线消息里面有一张图片(或者说离线消息体量 ...

客户端应该会有对每个会话的消息做merge吧
签名: now start 。。。
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部