高并发 IM 系统架构优化实践

互联网+时代,消息量级的大幅上升,消息形式的多元化,给即时通信云服务平台带来了很是大的挑战。高并发的IM系统背后究竟有着什么样的架构和特性?
以上内容由网易云信首席架构师内部分享材料整理而成前端

相关阅读推荐:java

推送保障及网络优化详解(一):如何实现不影响用户体验的后台保活
推送保障及网络优化详解(二):如何作长链接加推送组合方案
推送保障及网络优化详解(三):如何在弱网环境下优化大数据传输?

本文要点:git

网易 IM 云分层架构图解析

一、底层客户端 SDK,覆盖了安卓,iOS,windows PC 桌面端,web 网页端和嵌入式设备等多个平台。在 SDK 层使用的网络协议有 4 层的 TCP 协议和基于 7 层的 Socket.IO 协议,后者专门用于 Web SDK 中提供长链接能力;除了集成到应用 App 中的 SDK 以外,还提供了供第三方服务器调用的 API 接口,基于 Http 协议;最后的 A/V SDK 是基于 UDP 协议的实时音视频 SDK,用于实现基于网络的语音和视频通话。github

图片描述

二、网关层:提供客户端直接接入并维护与服务器之间的长链接;其中 WebSDK 直连的是 服务,这是一个基于 Socket.IO 协议实现的长链接服务,而供 AOS/IOS/PC等客户端 SDK 直连的是基于 TCP 协议的 Link 服务;在 Link 和 WebLink 服务中承担的一个很是重要的功能就是全部客户端长链接的管理,后面基于 HTTP 协议上的网关有 API 服务,和 LBS 服务等,其中 LBS 服务用于帮助客户端 SDK 选取最合适本身的网关接入点,优化网络效率;而 API 服务则直接提供来自第三方服务器的业务请求;web

三、HA 层:在网关接入层之上是 HA 层,网关接入层可提供给客户端直连,在 link 层和 Service 层之间有一个 HA 层用来解耦并提供高可用和易扩展等特性;在 HA 的具体实现方式上,对 Link 和 WebLink 这两个维持客户端长链接的服务,云信提供了协议路由的服务,代为分发业务请求,路由层会按照预约义的规则未来自客户端的请求转发到相应的业务节点上,当业务集群扩容以后路由服务立刻能发现新的可用节点,并将请求转发过去,当发现业务节点出现异常时也会被路由层标记并隔离下线以备替换。算法

四、业务节点集群:在 HA 层上就是具体的业务节点集群,咱们称为 App 服务,该服务处理具体的客户端请求,后端直连 DB、cache 等各类基础服务,这个集群中的节点的特色是轻量,而且每一个节点都是无状态的,云信在实际部署这个集群时会跨网络环境部署,好比在同城双机房中分别部署一套业务服务节点,前端经过路由层来分发业务请求,平时正常时业务互为热备,平均分担线上的业务流量;当单一网络环境或者基础设施出现故障时立刻会被路由服务检测到,并将该环境下的计算节点标记下线,将线上的流量请求所有转发到正常工做的集群中;从而提升了服务的总体可用性;配合监控平台等运维工具,业务节点的实时处理能力和容量使用状况都会被动态监测起来,当处理能力达到预设的水位线时会当即出发报警,运维人员能够很是方便快捷得经过自动部署平台对业务节点集群进行扩容。segmentfault

五、业务层:其中包含了一些关键功能:核心的单聊消息、群聊消息和聊天室,通知等;以及用户信息托管,特殊关系管理等;还有面向 API 提供的如短信业务,回拨电话和专线会议等;还有实时音视频和直播功能等相关能力。windows

最右边列出的是从服务层上单独列出来的更重要的功能,包括与开发者应用的第三方数据同步,个性化的内容审核支持,超大群服务,登录登出事件日志,漫游消息和云端消息历史功能,推送服务等等。后端

网易 IM 云部署拓扑

经过如下这张简化后的部署拓扑图能够对云信总体技术体系的有初步了解。最右边是客户端,客户端经过 LBS 服务获取到网关接入点列表,再与Link和WebLink这类长链接服务器创建起长链接,并进行 RPC 操做,全部来自客户端的请求都会经过路由层转发到后端的 APP 层,App 层实时处理并下发同步请求的处理结果,并把一些异步任务经过队列服务送到异步任务中,这些异步服务如大群消息的发送,推送服务,云端历史消息的存储和第三方的数据抄送同步服务等;在最下面的 API 接口上也是相似,API 直接提供给第三方的服务器调用请求,API 后端是各类独立的业务,如回拨电话,短信等;一样的全部的 API 后端业务请求也会产生相应的日志;和 App 上的日志样,这些日志都会被经过日志采集平台收集到大数据平台中,一方面这类数据会存储到 HDFS 上用于做为数据统计分析的数据源;另外一方面会被导入到 Hbase 等数据仓库中,用于提供日志检索和二次分析。浏览器

图片描述

高并发IM系统链接层的优化实践

即时通信功能中最重要的链接管理服务怎么作?消息快速到达的前提是客户端和服务器之间保持了稳定的链接;能够理解为奠基云信服务稳定性的基石。网关接入层须要解决的最重要的问题是什么?核心依然是稳定,安全和快速。

图片描述

如何保证稳定?网易云信 SDK 采用长链接机制来实现,而且由心跳的方式来检测断线和自动作重连,同时云信的 SDK 对移动网络等弱网环境很是多的优化工做,对移动端/PC 端使用 TCP 来链接客户端与服务器,对与 Web 端使用 socketIO 协议,实现长链接的同时解决浏览器的兼容性问题;

如何实现安全?,云信要求全部在公网传输的数据都必须被加密;在 SDK 与服务器的链接创建过程当中有一个复杂的秘钥协商过程,首先客户端须要生成一个一次性使用的加密秘钥,并使用非对称加密方式将这个秘钥加密以后传给服务器,加密数据会被服务器解密,以后该加密秘钥被保留在该长链接的会话信息中,数据来往均使用该秘钥加密,这是一个流式加密,能够有效防止中间人攻击和数据包回放等攻击手段。

如何保证快速?首先是在网关接入点的选择上,借助 LBS 服务能够帮助客户端寻找到最适合本身的网关接入点,好比从 IP 等信息判断到的物理距离最近节点,其次在链接创建以后,长链接的机制能够极大提高消息上下行的速度,而且在数据传输过程当中,云信会对数据包压缩传输,下降网络开销来升消息收发的速度;对频繁的先后台切换和重登录这种移动客户端场景,SDK 提供自动登陆和重连等机制,即在UI界面起来的同时已经提早把消息通道创建;在接入网关的选择策略中,经过并行来提高链接创建的速度(展现图);

客户端与服务器创建长链接的过程展示

SDK 接入的第一步是先请求 LBS 服务,获取能够进入的接入网关地址列表,LBS服务会根据多种策略条件来给客户端分配地址,常见的条件以下:
1:appkey, 经过 appkey 能够将一个特定的应用请求所有指向到一组特定的接入点,可用于专属服务器方案;
2:客户端 IP,用于根据客户端所处的地理位置,为其就近分配接入网关,常见于海外节点的配置;

  1. SDK 版本号,将特定版本范围的客户端指向到特定网关,经常使用于新老版本升级的兼容方案,目前无实际使用案例;
  2. 特定环境标识,如智能客服环境等,用于将特定类型的 app 指向到特定网关,用于较大粒度环境隔离需求;

在从 LBS 服务请求到接入网关地址以后,客户端会按列表中的地址依次尝试创建链接;若是严格按照这样的顺序,那客户端创建链接的过程就会偏慢,为了加速接入过程,实际上在操做时,SDK 都会使用本地缓存的最后一次 LBS 请求返回的地址列表来创建链接,同从 LBS 上拿一次新的地址列表缓存在本地,以备下次使用;当列表中的全部地址在尝试过一遍均失效,则会使用默认的 link 地址来创建链接;默认地址也失败是会出现 415 或者 408 这种网络错误码;

在获取到目标地址以后就会尝试创建 TCP 长链接,链接创建以后就会与服务器协商加密秘钥,并发出第一个鉴权包,鉴权完成以后这个长链接就是一个安全有效的链接,客户端能够发起后续的 RPC 请求;服务器也能够往这个链接上下发消息通知;若是秘钥协商失败或者鉴权失败,这个链接就会被认为是一个非法的链接请求,服务器会强制断开;

最后聊一下加速节点的问题,为了实现链接的快速,在网关接入点的分配时会优先距离该客户端最近的节点;这里将的加速节点就是为了更靠近用户提供的一种特殊节点。
加速节点的原理背景是运营商提供给我的用户的线路,无论是移动网络仍是有线网络,其质量和 IDC 中心之间的网络老是有差别的;若是将整个用户链路中的关键路径替换成 IDC 之间的网络线路,那么对提高链接的稳定性和速度是有帮助的。

假设一个处于美国的客户经过手机网络访问位于杭州的一个网关接入点,因为客户端所在的网络是一个移动网络,直连到杭州服务器须要通过的链路很是长并且可能跳转的中间节点不可预期,在中国来讲,还要跨越防火墙;因此直连的状况大部分可能就是没法链接,或者链接以后频繁断线。
咱们提供了多层的加速节点:加入了加速节点以后,用户的总体链路中原来不可预期的那段链路都换成了质量较好的线路,用户直连到本地的加速节点的网络每每就会好不少。

下面说说不一样的投递模式对消息送达效率的影响:

问题一:怎么让消息投递并发能力倍增?

图片描述

在这张图中,上半部分表示的是一个点对点型的 Link 服务器,当发送者A发送一条消息以后,经过 link 这条消息提交到 App 中处理,App 中查询到该消息接收者B所在的 link 服务器是 link y,因而向 link y 服务器下发一条下行通知包,link y 上再找到用户 B 对应的长链接并将通知下发到客户端;这种模式下,全部的接入点link 对于全部的用户来讲都是对等的,他能够接入到任何一个服务器中,任何消息的发送都必须在业务层查询到目标接收者所在的 link 服务器,并往相应的 link 服务器下发通知包,若是是一次群发行为,那就须要在业务 App 上把全部群内的成员所在的 link 列表都查询一遍;这是一个比较耗时的操做;而且是随着消息接收成员的数量不断上升开销不断增大;因此若是是须要往聊天室内发送消息,因为聊天室内的成员数量很是庞大,这种模式很快就会遇到性能瓶颈,消息投递的延时会很是严重;

对于广播型的 link 服务器,云信在分配接入点时首先遵循一个原则,那就是同个聊天室内的成员在分配聊天室时,尽可能分配在同一组接入点上;在 link 上维护了每一个房间内全部的成员的长链接集合;而在 App 上维护的再也不是特定用户和 link 以前的映射关系,而是维护了特定房间分配的 link 的集合;因而在任何一个成员发出一条聊天室广播消息以后,消息经过 link 上行到 App,App 只要找到该聊天室已经分配的 link 地址列表,往每一个 link 上下发一个广播消息,link 在收到下行的广播消息以后再在本地作广播分发;这个效率比点播的模式高出了不止一个数量级;

问题二:怎么解决单节点的性能瓶颈?

在讲完了点对点型和广播型这两种 link 的区别以后;云信再回头来看看另一类基于 socket.io 实现的 weblink 的代理方案在云信中的演变优化过程;
在这以前须要再强调下 WebLink 中两个关键点,首先 WebLink 是基于 Socket.io 协议的,为了保证数据通道的可靠,云信须要使用Https来对通道加密,其次因为是 Https 的请求因此必须提供独立的域名。

图片描述

图一中显示的是最先的方案,后端 Weblink 提供链接,并实现 SSL 加密,多个节点前面经过 LVS 作代理,域名绑定在 LVS 代理之上,LVS 代理之上再作 Keepalived 方案来保证 HA;这种方案对外暴露的域名只有一个,而内部实际有不少的节点,扩容对外也是透明的;Web 客户端在链接时只须要直连这个惟一域名就能够,对于单一产品来讲这种方式最简便快捷,客户端能够绕过地址分配的过程;缺点也集中在单一出口,若是这个单一出口受到 DDOS 攻击,只能经过域名换绑来规避,而域名换绑须要必定的生效时间,带来和一些运维上的代价,其次对于云信这种服务来讲,单一出口就丧失了灵活性;全部客户直连到同一个入口,也没法实现专属服务和业务隔离,没法实现加速节点方案;
因而便有了第二种方案,这种方案借鉴了 link 业务中的 LBS 分配的方式,仍是在 Weblink 节点上实现 SSL 加密,并为每一个 Weblink 节点分配独立域名,客户端在接入前先经过LBS服务来分配到合适的接入点;这种方案好处就是提供了更大的灵活性,随时能够给集群扩容,也能够动态调整特定应用的接入点地址,也提供作加速节点的可能性;可是这种方案的问题是每一个节点都是单点,并且节点内仍是须要作 SSL 编码,因为 java 的 SSL 对 CPU 资源开销比较大,在突发用户流量是会影响单个节点的服务能力;
因而又有了第三种方案,这种方案前端使用Nginx作七层代理,并在 Nginx 配置 SSL 和域名绑定,后端能够同时使用一组 Weblink;因为使用了 Nginx,在端口的分配逻辑上也更加科学,提升了运维的便捷性;最后云信就获得了目前在使用的一个组合方案,前端仍是经过 LBS 服务来为 SDK 分配接入点,以此提供灵活性;后端使用多个 Nginx 集群作代理集群,每一个集群分组的性能都获得了提升。

即时通信平台服务化和高可用实践

前面重点介绍了云信在客户端接入层的实现和接入点的管理上使用的一些方法,经过这些技术手段为 IM 服务创建了一条稳定可靠的消息通道,如今来聊聊在业务层作的服务化和高可用上面的工做。

图片描述

网关接入层负责客户端长链接的维护和管理,全部的接入节点甚至能够是无状态的对等节点,只负责客户端与服务器之间请求的传递的转发,并优化转发效率;而真正的业务处理逻辑仍是须要有业务层来实现。

业务层须要处理大量请求并负责和 DB,缓存,队列,第三方接口等组件的交互,其稳定性,可用性和扩展能力直接影响了整个云服务的质量;为了使业务层具备更好的弹性,云信在网关接入层和业务层之间引入了一个路由层来解耦;业务节点在上线以后会将本身注册到服务中心,路由节点会转接网关层的请求包,并从服务节点中挑选匹配的节点分发请求;这种三层架构使系统总体具备更好的弹性。

为了提升业务的可用性,云信会将业务节点分布到分属于不一样网络的环境中,正常状况下能够同时提供服务,一旦其中一个环境的网络或者基础设施出现故障,就能够快速得经过路由层来将故障集群下线。
灵活支持灰度升级模式,云信能够将其中部分业务节点升级,而后经过路由层的配置将指定的用户流量导入到新升级的节点中;
专属服务的灵活支持,对于一些对资源独占需求比较强烈的客户,云信能够经过路由层将该客户应用下的全部流量导入到独立的集群中。


随着即时通信以及音频处理和压缩技术的不断发展,效果更好、适用范围更广、性能更高的算法和新的技术必将不断涌现,若是你有好的技术或者分享,欢迎关注网易云信官方博客和 GitHub:

关注更多技术干货内容: 网易云信博客
欢迎关注 网易云信 GitHub
欢迎关注 网易云信官网
相关文章
相关标签/搜索