Jack Jiang

我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
posts - 467, comments - 13, trackbacks - 0, articles - 0

本文由网易云信资深服务端开发工程师曹佳俊分享,本文收录时有内容修订和重新排版。

1、引言

聊天室是一类非常重要的 IM 业务形态,不同于单聊和群聊,聊天室是一种大规模的实时消息分发系统。聊天室有多种技术实现方案,业界也有一些开源的实现,每种实现都有自己的特点和应用场景。

本文将分享网易云信针对海量用户IM聊天室的架构设计与应用实践,希望能带给你启发。

 
技术交流:

(本文已同步发布于:http://www.52im.net/thread-4404-1-1.html

2、本文作者

曹佳俊:网易云信资深服务端开发工程师,中科院研究生毕业后加入网易,一直在网易云信负责 IM 服务器相关的开发工作。对 IM 系统构建以及相关中间件的开发有丰富的实战经验。

3、聊天室整体架构

首先,我们先来看一下网易云信当前聊天室的详细技术架构,以及我们在架构升级优化过程中做的一些事情。

如下图,是网易云信聊天室的技术架构:

主要包括以下部分:

  • 1)接入层的 ChatLink;
  • 2)网络传输层的 WE-CAN、WE-CAN bridge;
  • 3)调度层的 Dispatcher;
  • 4)服务层的 Callback、Queue、Presence、Tag、History 等;
  • 5)CDN 分发层的 CDN Manager、CDN Pusher、CDN Source。

下面,我们针对每一层展开详细分析。

4、聊天室的接入层

接入层根据客户端的类型不同会有不同的实现,例如常见客户端(iOS、Andriod、Windows、Mac 等)基于私有二进制协议,Web 端基于 Websocket 协议实现。

接入层作为距离客户端的最后一公里,其接入速度、质量以及数据安全都是至关重要的,下面我们逐一讨论。

1)接入速度和质量:

目前我们搭建了覆盖全国各省份以及全世界各大洲的边缘节点,缩短最后一公里,减少不确定性,提升服务的稳定性。

2)数据安全:

基于对称+非对称加密,客户端与服务器之前实现 0-RTT,完成秘钥交换和登录,同时也支持 RSA/AES/SM2/SM4 等各种加密算法。

接入层除了接受来自客户端的请求,还负责进行消息的单播和广播,因此接入层需要管理本节点的所有长连接,包括每个聊天室房间的连接以及每个连接的标签属性。

此外接入层会上报自己的负载信息给后端服务,方便调度层进行合理的调度。

当流量洪峰来临时,因为需要进行消息的广播,接入层往往是压力最大的,为了保证服务的稳定性,我们做了很多优化策略。

3)自适应的流控策略:

单机流控:接入层服务会监控本机整体的网络带宽使用情况,并设置 2 个阈值 T1 和 T2,当带宽使用率超过 T1 时,触发流控,如果进一步超过了 T2,则不仅触发流控还会不断的调整流控的强度。最终的目标是使带宽使用率稳定在 T1 和 T2 之间。

单连接流控:除此之外,接入层服务还会记录每个长连接的消息分发速度,并进行细粒度的调整,避免单机粗粒度流控导致单个连接分发过少或者过多,做到消息分发的平滑,即减少了带宽流量的波动尖刺,也改善了端侧的体验。

4)性能优化:

ChatLink 高负载运行时,除了网络带宽,调用链路上的各个环节都可能成为性能的瓶颈。我们通过减少编解码的次数(包括序列化、压缩等)、多线程并发、减少内存拷贝、消息合并等多种方式,显著地提升了服务性能。

5、聊天室的网络传输层

我们的IM聊天室系统最初的架构是将接入层和后端服务层都部署在同一个机房的,大部分用户都是直连 BGP 机房的 ChatLink,对于偏远地区或者海外,则通过专线的方式部署代理节点完成加速。

该方案存在明显的缺点就是服务能力上限受制于单机房的容量。此外,专线也是一笔不小的开销。

在我们接入 WE-CAN 大网后,接入层 ChatLink 可以做到客户端就近接入,提高服务质量的同时降低了成本。此外,多机房的架构也使得我们的服务能力上升了一个台阶。

为了适配 WE-CAN 大网,我们设计了 WE-CAN Bridge 层,作为大网接入协议和聊天室协议的桥接层,负责协议转换、会话管理、转发接收。通过这种分层架构,接入层和后端业务层可以少修改或者不修改,减少对已有系统的改造成本,也降低了架构升级带来的风险。

什么是WE-CAN?

WE-CAN(Communications Acceleration Network)是网易自研的新一代大规模分布式传输网络,WE-CAN的根本目标是建立一个能将任意数据从全球任一点稳定、快速、高效地发送到全球任何其他角落的通用传输网络,且这个网络是架设在公共互联网之上的 —— 即无需借助任何特殊的硬件设备或架设专线,而是通过软件方案来达到目标。

6、聊天室的调度层

调度层是客户端接入聊天室系统的前提。客户端登录聊天室之前需要先获取接入地址,分配服务我们称之为 Dispatcher。

Dispatcher 是中心化的,会接受来自 WE-CAN 和 ChatLink 的心跳信息,根据心跳情况来选择最佳接入点。

调度系统设计主要考虑的是以下两个关键点。

1)调度精度:

调度系统会根据请求方的 IP 判断地域和运营商信息,对比各个边缘节点的所属区域、运营商以及节点本身的负载(如 CPU、网络带宽等)。

此外还考虑边缘节点到中心机房的链路情况(来自 WE-CAN),计算综合打分,并把最优的若干节点作为调度结果。

2)调度性能:

面对高并发场景,比如一个大型聊天室,活动初期往往伴随着大量人员的同时进入,此时就需要调度系统做出快速的反应。

为此,我们会将上述的调度规则以及原始数据进行本地缓存优化。

此外,为了避免心跳信息滞后导致分配不合理引起节点过载,分配服务时还会动态调整负载因子,在保证调度性能的前提下,尽量做到分配结果的平滑。

7、聊天室的服务层

服务层实现了各种业务功能,包括:

  • 1)在线状态;
  • 2)房间管理;
  • 3)云端历史;
  • 4)第三回调;
  • 5)聊天室队列;
  • 6)聊天室标签等。

其中最基础的是在线状态管理和房间管理:

  • 1)在线状态管理:管理某个账号的登录状态,包括登录了哪些聊天室、登录在了哪些接入点等;
  • 2)房间管理:管理某个聊天室房间的状态,包括房间分布在哪些接入点,房间里有哪些成员等。

在线状态管理和房间管理的难点在于如何有效管理海量用户和房间。

由于 PaaS 平台的特性,使得我们可以根据不同的租户来进行 Region 划分,从而做到水平扩展。

此外:由于状态数据有快速变化的特点(短 TTL),当某些核心用户或者某个客户报备了大型活动时,可以在短时间内进行相关资源的快速拆分和隔离。

服务层除了要支持海量客户接入、水平扩展外,还有一个很重要能力,就是需要提供各种各样的扩展性功能来适配客户各种应用场景。

为此我们还提供了丰富的功能,比如:

  • 1)第三方回调:方便客户干预 C 端用户的登录、发消息等核心环节,自定义实现各种业务逻辑(因为涉及到服务调用,而这个调用是跨机房甚至是跨地区的,为了避免第三方服务故障导致云信服务异常,我们设计了隔离、熔断等机制来减少对关键流程的影响);
  • 2)聊天室队列:可以方便用户实现一些诸如麦序、抢麦等业务场景需求;
  • 3)聊天室标签:作为特色功能,支持消息的个性化分  发(其实现原理是通过客户端登录时设置标签组以及发消息时设置标签表达式,来定义消息分发和接收的规则。标签信息会同时保存在服务层以及接入层,通过将部分标签计算下推到接入层,节省了中心服务的带宽和计算资源)。

8、聊天室的CDN 分发层

当我们评价一个牛x的IM聊天室系统时,常用的一个词是无上限。

架构支持无上限不代表真的无上限。

一个IM聊天室系统,在逻辑上,各个组成单元都是可以水平扩展的,但是每个服务所依赖的物理机、交换机、机房带宽等都是有容量上限的。因此,能够合理地调配多个地域的多个机房,甚至是外部的其他资源,才能真正体现出一个聊天室系统所能支撑的容量上限。

在我们的聊天室系统中,用户所有的接入点遍布各地机房,天然的将各地的资源进行了整合,所能支撑的容量上限自然高于单机房或者单地区多机房的部署模式。

进一步的:当面临一个更大规模的聊天室,此时如果能利用一些外部的通用能力不失为一种合适的选择。融合 CDN 弹幕方案就是这样一种技术实现方案,它可以利用各大 CDN 厂商部署在各地的边缘节点,利用静态加速这样的通用能力来支持超大规模的聊天室消息分发。

基于融合 CDN 弹幕分发方案,其核心点就是弹幕的分发和管理,这是一个可选的模块,我们内部对此进行了封装,可以根据不同的业务特点来选择是否开启而不需要修改任何业务代码。

在开启融合 CDN 弹幕分发方案的情况下,所有的弹幕广播会划分成两条链路:

  • 1)重要的且需要实时送达的消息会走长连接到达客户端;
  • 2)其他的海量消息则会进入 CDN Pusher,通过各种策略进行聚合后送达 CDN Source。

客户端 SDK 会采取一定的策略定时从 CDN 边缘节点获取弹幕消息。SDK 会聚合不同来源的消息,排序后回调给用户,App 层无需关系消息来自哪里,只需根据自己的业务需求进行处理即可。

如上图,展示了 CDN 弹幕分发链路的消息流转过程。

CDN Manager 负责:

  • 1)管理不同 CDN 厂商的分配策略(登录时会通过长连接下发,且能动态调整)
  • 2)负责管理平台上各个聊天室融合 CDN 模式的开启和关闭;
  • 3)对应的 CDN Pusher 资源的调配和回收。

CDN Pusher 实际负责:

  • 1)接收来自客户端消息;
  • 2)并根据消息的类型、消息的优先级等,组装成以一个一个的静态资源,推给 CDN Source,等待 CDN 回源拉取。

9、大规模场景应用案例

在2020年8月,网易云音乐 TFBoys 的 7 周年线上演唱会就是一个聊天室大规模场景应用的典型案例。

在这场活动创造了 78w+ 的在线付费演唱会的世界纪录,其弹幕互动的实现方式采用了我们基于融合 CDN 弹幕分发方案。

事实上:在筹备环节,我们的聊天室系统达成了 20 分钟完成从 0 到 1000w 在线,上行消息 tps 达到 100w 的性能指标。

如上图:是支持本次活动弹幕分发的架构图,普通弹幕和礼物消息分别通过客户端 SDK 以及服务器 API 到达云信服务器,并最终进入弹幕广播服务,随后分流到长连接和 CDN 上,再通过 pull / push 混合的方式送达客户端。

PS:有兴趣的同学可以深入阅读关于这个案例的技术分享:《直播系统聊天技术(九):千万级实时直播弹幕的技术实践》。

10、聊天室标签应用案例

近年来,随着互联网的发展,在线教育越来越火爆,最近又兴起了“超级小班课”模式。

所谓超级小班课,指的是大型多人课堂与小班互动模式结合。在线直播场景下,文字互动作为其中重要的一环,是IM聊天室的典型应用场景。

但在超级小班课的模式下,常规的IM聊天室系统却存在各种各样的问题,不管是建立多个聊天室,还是单个聊天室进行消息过滤,都存在一些严重的问题。

由此我们开放了聊天室标签功能,完美支持了上述业务场景。

基于聊天室标签:可以灵活地支持聊天室消息定向收发、聊天室权限定向管理、聊天室成员定向查询等个性化功能,真正实现大型直播下多场景的分组互动。

比如:

  • 1)对学生进行分组标签后,方便进行因材施教;
  • 2)分小组讨论,小组间内部讨论和组间 PK 等等。

如上图,展示了超级小班课的一个场景:1 个主讲教师+ N 个互动小班+ N 个助教,所有学生被划分成了一个一个的小班,由对应的助教完成预习提醒、课后答疑、作业监督、学员学习情况反馈等工作,同时又接收来自主讲老师的直播画面,做到了大课的规模,小课的效果。

11、本文小结

以上,就是本文的全部分享,主要介绍了我们构建一个大型聊天室系统的主要技术以及架构原理。

任何系统的搭建都不是一蹴而就的,我们也会继续打磨底层技术,就像引入 WE-CAN 来提升网络传输效果,也会继续丰富完善我们的功能图谱(如独创的聊天室标签功能等)。

12、参考资料

[1] 直播系统聊天技术(九):千万级实时直播弹幕的技术实践

[2] 海量实时消息的视频直播系统架构演进之路(视频+PPT)

[3] 百万在线的美拍直播弹幕系统的实时推送技术实践之路

[4] 阿里电商IM消息平台,在群聊、直播场景下的技术实践

[5] 微信直播聊天室单房间1500万在线的消息架构演进之路

[6] 百度直播的海量用户实时消息系统架构演进实践

[7] 百万人在线的直播间实时聊天消息分发技术实践

[8] 直播间海量聊天消息的架构设计难点实践

[9] vivo直播系统中IM消息模块的架构实践

[10] 万人群聊消息投递方案的思考和实践

[11] IM中的万人群聊技术方案实践总结

(本文已同步发布于:http://www.52im.net/thread-4404-1-1.html

posted @ 2023-09-01 10:39 Jack Jiang 阅读(130) | 评论 (0)编辑 收藏

本文由QQ技术团队王辉、吴浩、陈俊文分享,编辑Tina整理,本文收录时有内容修订和排版优化。

1、引言

在瞬息万变的互联网行业中,年过二十四的即时通讯IM应用 QQ 堪称超长寿的产品,见证了中国互联网崛起的完整历程。

然而,如今这个元老级产品经历了一次从内到外彻底的重构。在这次重构中,QQ 选择了 Electron 作为 UI 跨平台开发框架。

尽管 Electron 被 Slack、Visual Studio Code 和 Discord 等大型产品广泛使用,但也引发了一些网友的担忧,例如内存占用、安装包体积和启动速度等方面的问题。本文内容整理自 QQ 技术团队的采访,我们一起来看看QQ团队选择Electron作为桌面版跨端框架背后的决策与思考。

 
 
技术交流:

(本文已同步发布于:http://www.52im.net/thread-4391-1-1.html

2、系列文章

本文是系列文章中的第8篇,本系列总目录如下:

3、老QQ桌面版的技术债

3.1多端代码不统一

QQ 的第一个版本发布于 1998 年,在 Windows 技术栈的基础上用纯原生的方式开发,在当时互联网带宽非常小的情况下,QQ 将安装包控制在了只有 200K 左右。

2007 年后智能手机开始露出苗头,腾讯行动得比较早,部分前端技术开发开始转型到了移动端,在桌面端, QQ 随着业务和组织的发展,针对三大操作系统陆续组建了三支不同的研发团队,各自负责自己的一套代码。

▲ 初版QQ的注册向导页

▲ 初版QQ的主要功能为即时聊天

三端不同代码,老产品历史包袱,加上移动时代研发人员的转型,导致桌面 QQ 维护成本很高。

QQ 技术团队介绍,拿之前的桌面 QQ 为例,Windows QQ 以前的 UI 框架用的是腾讯自研的 GF 框架,10 多年了,GF 这个框架文档还不全,新加入这个项目的团队人员,要基于这个基础框架去做一些事情,是效率很低的一件事情,慢慢的就没有人愿意去用这个框架了。简而言之,就是技术债。

PS:如果你对QQ的发展史感兴趣可以看看下面这些文章:

  1. 闲话即时通讯:腾讯的成长史本质就是一部QQ成长史
  2. 技术往事:创业初期的腾讯——16年前的冬天,谁动了马化腾的代码
  3. 技术往事:史上最全QQ图标变迁过程,追寻IM巨人的演进历史
  4. QQ的成功,远没有你想象的那么顺利和轻松
  5. 还原真实的腾讯:从最不被看好,到即时通讯巨头的草根创业史

3.2多端功能不一致

旧版的桌面端 QQ,Windows 的功能最丰富,Mac OS 次之, Linux 功能非常简洁。

比如“屏幕共享”这个功能,移动端有,Windows 端有,但是 Mac OS 端是没有的。那用户就会遇到一个问题,像 Mac OS 端无法与其它端 QQ 用户一起来使用这个功能。

“多端不统一不利于用户对于 QQ 的统一认知。我们这次的架构升级就是想尽量通过一套核心代码去拉平所有平台的体验,让它具有更好的可维护性和可扩展性,让桌面 QQ 能够更好地迭代产品交互和功能,升级用户体验,再次焕发生长的生命力。”

3.3QQ NT 项目的诞生

于是 QQ NT 项目的诞生了!

QQ NT 项目是在 2022 年 3 月份正式启动, Mac OS QQ 在 6 月份开始发布内测, 9 月份正式上架了 App Store,迭代了几个版本之后,QQ 团队就同步开发 Linux。

在 2022 年,QQ 发布了新的 macOS 和 Linux 版本,包括 QQ 后台其实也做了很大的改变和重构,核心系统做了全新重写,云原生成熟度也得到了很大的提升。

从 2023 年开始,QQ 团队聚焦做 Windows 端的开发,在 3 月底就开始内测,7 月初上架官网。

同时移动端 QQ NT 也在 7 月初完成了核心系统的重写和全量升级。

在目前全新的框架设计下,无论是核心系统、功能迭代还是设计语言上,都可以尽可能地“原子化”,来让 QQ 后续更好地迭代功能。

4、新QQ桌面版重构的技术挑战

4.1业务功能上的挑战

QQ 的重构其实是两方面的重构:

  • 1)一个是面向复杂业务的梳理重构;
  • 2)一个是面向工程技术债的全新技术重构。

重构之路也是两者相互伴随的过程。

首先:在整个 QQ 重构过程中最大的挑战来自于 QQ 功能的复杂化,QQ 有很多十分复杂的历史功能,这些功能模块也曾经由非常多不同的人经手负责过。其中哪些功能是不合理的或没有价值的,如何去做取舍往往是最难的。“虽然技术上我们做了很多事情,但技术上的实现或许并没有那么难,我们处理起来更有经验和从容。相比于技术的复杂度,业务上的往往需要考虑的更多,这本身就是很大的挑战。”

因为 QQ 已经是近 25 年的产品了,有很多细小复杂的功能。虽然这些功能看看起来很小,但用户量其实又很大,稍微改动可能就会有很多的用户反馈,QQ 团队都得非常的关注。仅从产品功能角度上看,有些功能本身就已经是很重的负债,而 QQ 团队内部有一个叫做“QQ 节能计划”的项目,会有比较严谨的项目流程去评估是否需要下架。

4.2技术重构上的挑战

技术上重构也有不少挑战,这次重构是一次跨平台的重构,而在多个平台里面比较有挑战则是 Linux 平台。

作为程序员,很多人免不了要跟 Linux 打交道。但是这么多年来,对于使用 Linux 系统的用户来讲,有一个特别让人烦恼的问题,那就是没有一个好用的 IM 聊天工具。被寄予厚望的 QQ,此前在 Linux 版本上功能也没有 Windows 和 Mac OS 版本全面,迭代速度也明显慢过其他两个版本。业界甚至猜测 Linux 第一个版本是由腾讯实习生所写,毕竟这个说法进一步加重了其初版的“简陋”特性,也为其“停更”的原因提供了更合理的解释。

QQ 技术团队表示,较之另两个版本,Linux 版本的研发最为复杂:

  • 1)一方面操作系统本身很多碎片化,市面上有非常多的发行版,也不缺乏一些千奇百怪的版本;
  • 2)另一方面因为机器运行环境或编译器的缺失,使得解决适配问题的难度很大。

许多发行版相关的机器和开发环境实际上他们并没有,有时还需要外部公司帮助进行一些测试工作。由于没有相应的开发环境,一旦出现闪退等问题,解决难度自然会变得更大。此外,有时候需要与国产操作系统厂商进行特殊的合作,甚至需要对方寄送特定的编译好的代码库,但前后往往会花费一个月的时间才能收到。

而在本次重构之后,“Linux 功能跟 Windows 一样多了”。

4.3选型Electron的质疑

技术上的另一大挑战便是外界对于 QQ 桌面端使用 Electron 的质疑,尤其是内存方面。

外界有些用户在没有使用和分析的情况下对此发表一些夸大和否定的言论,也确实给 QQ 技术团队带来不小压力,但他们却始终坚定选型方向,也相信其中的问题可以被攻克和解决。

5、为何选择Electron而非纯Native技术栈?

5.1为什么Windows端不用原生实现?

确实当时有很多人在问,为什么 Windows 不用原生去实现?为什么不用 Qt?

首先:不太想和以前一样,Windows、Mac OS、Linux 三端各由一个团队分开负责。在国内这种人才环境里面,相关的纯原生的开发人员其实非常难招了,桌面端的人才稀缺,同时也投入比较大。

而对于 Qt 技术栈,他们首先考虑的其实还是人才的问题,国内熟练 Qt 技术栈的人非常少。如果对这个框架不了解,使用它反而是一个负向作用。

至于微软的 Webview2,从本质上讲,Webview2 和 Electron 并没有太大的区别,只是相对在其中打包了一些微软自身的优化措施,其他方面也不是很完善,而且还无法跨平台。虽然内存方面相较于 Electron 做了更多的优化。但据了解,比如微软 Teams 也没有完全切到 Webview2。并且由于它没有开源,因此也没有办法基于 Webview2 做定制优化。

包括 Flutter,QQ 团队表示他们当时也有过调研。他们放弃的一个原因是 Flutter 在桌面端的完善程度并不高,也担心标准化的问题。虽然当前 Flutter 非常流行,但谁也说不好这是不是“2015 年的 React Native”。大家担心随着时间推移,这套技术可能会失去维护支持,因为本身 Google 使用 Flutter 的占比也比较小。

“虽然它很热,但我们历史上踩过了很多很多非标准化的坑,一旦某个技术栈热度一过、维护力度不够,它就会成为全新的负债,做选型时必然也是避免再有类似经历。”

5.2选择Electron的几个考量

至于为什么最后选择 Electron,QQ 技术团队表示主要是基于以下几个考量。

1)首先最看重的是框架成熟度和技术栈的标准化:

Electron 基于 Web 技术栈,有足够低的上手和使用成本,不需要为了使用框架本身,还需要投入额外巨大人力成本去做基建和周边工具链的建设,以前在 RN、Flutter 的实践上都有类似的情况。而使用 Electron,现有的 Web 前端的大部分基建都可以直接复用,而且使用 Web 开发 UI 的效率,在主流技术栈里算是很高的了。至于迭代效率我觉得从新版桌面 QQ 功能的迭代速度就可以证明,这放在以前是完全办不到的。

另外由于 Web 技术栈是标准化的,假如 Electron 修改开源协议或者要闭源了,他们也能很方便的去写出一套类似的框架。只不过现在已经有开源的了,没必要再去重复建设一个。而且随着 Web 标准长久发展,Web 技术栈也不会有大的问题,而且还会越来越好。

2)其次是技术经验及人才储备:

技术选型是否适合当前团队也是一个很重要的考虑点,团队是否有相关的技术积累,是否有人才储备来持续投入这个技术栈。

Qt 的确在性能上是一个很好的选择,但目前团队对 Qt 没有太多积累,基建基本没有,而且相关人才其实比较匮乏,招聘就更难了。

而当前 QQ 技术团队 Web 前端团队还是有比较多的积累,在 QQ 频道项目中,也完整验证了 Electron 的技术可行性。

3)最后就是 Electron 具备的桌面端跨平台的优势:

但 QQ NT 架构并不是仅指 Electron,Electron 主要是作为 UI 跨平台的框架,只是占比很小的一部分,并且 QQ 桌面端不是全部用 Electron 实现,QQ NT 最核心的部分还是 QQ 底层通用抽象的模块,称之为 NT 内核,包括核心登录、消息系统、关系链、富媒体、长连接、数据库等等模块,完全用 C++ 实现,全平台通用。因此底层是完全跨平台的架构,而 Electron 只是上层桌面端 UI 跨平台较薄的一层。

“其实我们当时选型的时候,也的确看得到大家对 Electron 的评价褒贬不一,但我们还是有信心去解决这个问题,前期也做了一些技术的 Demo 和预研。实际上 Electron 并没有糟糕到这个地步。我们觉得可能是国内很多没有用过 Electron 的开发者,对这个框架有些忌惮。其实你到 Electron 的网站去看,还是有非常多国内外的亿级 DAU 产品都使用 Electron 框架。目前这几年主流的桌面端应用基本都选择了 Electron,如 Visual Studio Code、Discord、Slack、Skype、Whatsapp、Figma 等等,新的应用基本上也是首选 Electron,版本的迭代速度和社区氛围都很在线。”

“我们觉得不需要单纯因为口碑问题,就对这个选型没有了期待。还是要从实际出发,哪种技术栈适合你的产品,看看到底能不能有技术实力去把这个事情搞定。”

6、如何有效控制Electron的内存占用?

外界之所以会觉得 Electron 内存占用高,是因为其本身是一个多进程的架构,主进程基于 Node.js, 而每个窗口都对应一个渲染进程以及 V8 实例。可以说从技术框架层面上,上手写代码很容易,但不容易去管控它的内存。

QQ 技术团队认为:Electron 的开发者更多的是前端的开发者,可能在思维上没有去考虑怎么在这样一套技术框架里,去对内存数据进行管理和管控。开发者需要从前端开发者的思维,转变为客户端开发者的思维。

综合来看:对内存的看法其实不完全是 Electron 的技术框架所导致的,更多的是门槛上、开发思维上,导致内存没有得到很好的关注和优化。其实最简单的 Electron 应用大概也就只有几十兆的内存占用。因为前端原本更多还是停留在开发即用即走的 Web 站点,很少实现一个超大客户端,缺乏控制内存的经验,所以面对 QQ 这么大一个产品的时候,你就必须非常在意内存的使用和管控。

至于优化内存的突破口,可以说是从各个层面:从消息的链路中的每条消息的收发上,数据是怎么管理,包括像窗口及会话的管理,都得精打细算,也会做一些数据本地化和一些机制的按需加载,包括渲染上他们也提出一个根本的原则:“要做到所见才占用”,既我们看到的内容才占用这一部分内存,没看到和用不到的任何场景的内存就不应该再占用,通过各种方式来去让内存达到一个设定的目标。

他们也使用了不同维度的内存分析工具,从 V8 引擎到进程,再到整个应用程序,打通整个链路进行多角度的细节分析,以此来定位内存使用的瓶颈。之后采取一系列的针对性优化策略,包括缓存策略、按需加载、优雅降级等,同时使用线上监控、自动化测试手段,包括借助开发框架、工具建设、代码审查等,来阻止性能退化。(更多细节可以参看技术文章:《IM跨平台技术学习(九):全面解密新QQ桌面版的Electron内存占用优化》)

经过一系列组合优化之后:QQ 的内存在长时间挂机的条件下,平均稳定在 220M 左右。“现在优化还是不错的,比老版本要好很多。我们认为这个难题还是可以被很好的攻克,内存并不是大家认为的这么不可控,但是也需要团队去花费相当精力去探索和实践,才能去把内存控制到一个比较理想的状态。”

7、未来展望

目前 QQ 的前端团队作为一个公线团队,不仅负责桌面 QQ 的研发,还有 QQ 基础运营、QQ 空间以及基于 QQ 生态的创新项目研发,有比较多的线上项目的开发与维护和内部研效工具的建设。涉及的技术栈,包括 H5、Electron、Cocos、小程序、WebGL、WebAssembly、WebRTC 等。他们也表示会继续夯实这些技术,同时也不断地打破立下的性能目标,希望让桌面 QQ 覆盖更多平台。

他们也正在积极拥抱 AI:让 AI 在质量和效率上辅助日常开发。比如:前端设计稿还原,之前更多是一个耗时的体力活,D2C 是 QQ 前端一直探索的方向,之前使用纯规则转换生成代码,在视觉还原上效果还不错,但是代码可读性和可维护性不能很好的满足预期,所以除了一些日抛型的运营活动有些使用之外,比较难扩大成果。现在 D2C 结合大模型,生成的代码质量高了很多,也能很方便的将代码与 UI 组件库做映射,达到可以在核心业务中高效使用,达到通过 AI 提升研发效率的目的。针对一些无设计稿的管理平台开发,使用 P2C 提效,目前也有了一些不错的案例。

另外:QQ 技术团队也在积极探索 AI 更广阔的应用场景,比如代码评审,基本的 Lint 检检是难以实现的,但将已经掌握的内存泄漏模式通过规则的形式给到 AI,可以很方便地给开发同学一些不错的建议,为性能看家护院提供多一道保障。

8、写在最后

QQ NT 项目于 2022 年 3 月份启动,Mac OS QQ 花了该团队 3 个月的开发时间,9 月份上架 App Store,迭代了几个版本后同步开始开发 Linux QQ,并于这一年的最后一天上架各 Linux 应用市场,作为给 Linux 用户的一份特殊的新年礼物。2023 年 QQ 团队开始去聚焦做 Windows QQ NT 的开发,7 月正式上架应用市场和官网。同时移动端的 QQ 从 2022 年的 Q4 开始开发,也已经完成了全量升级和发布。

另外:桌面 QQ 也是在 NT 版本中第一次支持 64 位,这需要将音视频、安全、字节码、图形库等 C++ 模块,包括 Electron 框架都重新进行编译,花费了比较大的工作量。但在 64 位系统上,QQ 从此便不再需要以 32 位应用的方式通过额外的兼容和转换来运行。毕竟额外操作会增加开销,导致性能下降。

至此:QQ 实现了多个系统平台之间架构的统一。而团队的未来规划还是不断地打破性能目标,并覆盖更多平台,同时探索更多提升研发效率的办法,加快研发速度。

腾讯 QQ 用跨平台 Electron 取代之前原生应用程序的开发模式,这一举动引发的反响确实巨大。但我们也能看出,不同于小型产品团队,在大公司里具有一定规模的产品组织架构之下,快速满足用户需求,并逐渐需要为第三、第四乃至第五种运行平台提供支持时,保持一致性和协调性并不是想象中的那么容易。而缓慢而低效,最终会令你输掉比赛。

不管使用什么跨平台开发框架,都要去选择最合适自己团队的,也因此在 Web 标准技术栈上有丰富积累的 QQ 团队才会选择 Electron。并且我们认为没有人真正讨厌 Electron,只是我们对 QQ,对国内 App 寄予了非常高的期盼。

9、相关资料

[1] Electron官方开发者手册

[2] 快速了解新一代跨平台桌面技术——Electron

[3] Electron初体验(快速开始、跨进程通信、打包、踩坑等)

[4] Electron 基础入门 简单明了,看完啥都懂了

[5] vivo的Electron技术栈选型、全方位实践总结

[6] 融云基于Electron的IM跨平台SDK改造实践总结

[7] 闲鱼IM基于Flutter的移动端跨端改造实践

[8] 网易云信基于Electron的IM消息全文检索技术实践

[9] 闲话即时通讯:腾讯的成长史本质就是一部QQ成长史

[10] 技术往事:创业初期的腾讯——16年前的冬天,谁动了马化腾的代码

[11] 技术往事:史上最全QQ图标变迁过程,追寻IM巨人的演进历史

[12] QQ的成功,远没有你想象的那么顺利和轻松

[13] 还原真实的腾讯:从最不被看好,到即时通讯巨头的草根创业史

附录:更多有关QQ、微信的技术故事

技术往事:微信估值已超5千亿,雷军曾有机会收编张小龙及其Foxmail

QQ和微信凶猛成长的背后:腾讯网络基础架构的这些年

2017微信数据报告:日活跃用户达9亿、日发消息380亿条

腾讯开发微信花了多少钱?技术难度真这么大?难在哪?

技术往事:“QQ群”和“微信红包”是怎么来的?

开发往事:深度讲述2010到2015,微信一路风雨的背后

开发往事:微信千年不变的那张闪屏图片的由来

开发往事:记录微信3.0版背后的故事(距微信1.0发布9个月时)

一个微信实习生自述:我眼中的微信开发团队

首次揭秘:QQ实时视频聊天背后的神秘组织

为什么说即时通讯社交APP创业就是一个坑?

微信七年回顾:历经多少质疑和差评,才配拥有今天的强大

前创始团队成员分享:盘点微信的前世今生——微信成功的必然和偶然

即时通讯创业必读:解密微信的产品定位、创新思维、设计法则等

QQ现状深度剖析:你还认为QQ已经被微信打败了吗?

[技术脑洞] 如果把14亿中国人拉到一个微信群里技术上能实现吗?

QQ和微信止步不前,意味着即时通讯社交应用创业的第2春已来?

那些年微信开发过的鸡肋功能,及其带给我们的思考

读懂微信:从1.0到7.0版本,一个主流IM社交工具的进化史

同为IM社交产品中的王者,QQ与微信到底有什么区别

QQ设计团队分享:新版 QQ 8.0 语音消息改版背后的功能设计思路

社交应用教父级人物的张小龙和马化腾的同与不同

专访马化腾:首次开谈个人经历、管理心得、技术创新、微信的诞生等

一文读懂微信之父张小龙:失败天才、颠覆者、独裁者、人性操控师


(本文已同步发布于:http://www.52im.net/thread-4391-1-1.html

posted @ 2023-08-25 15:24 Jack Jiang 阅读(113) | 评论 (0)编辑 收藏

关于MobileIMSDK

MobileIMSDK 是一套专门为移动端开发的开源IM即时通讯框架,超轻量级、高度提炼,一套API优雅支持 UDP 、TCP 、WebSocket 三种协议,支持 iOS、Android、H5、标准Java、小程序、Uniapp,服务端基于Netty编写。

工程开源地址是:

关于RainbowChat

► 详细产品介绍:http://www.52im.net/thread-19-1-1.html
► iOS端更新记录:http://www.52im.net/thread-2735-1-1.html
► 全部运行截图:iOS端全部运行截图 (另:Android端运行截图 点此查看
► 在线体验下载:App Store安装地址 (另:Android端下载体验 点此查看

 

RainbowChat是一套基于开源IM聊天框架 MobileIMSDK 的产品级移动端IM系统。RainbowChat源于真实运营的产品,解决了大量的屏幕适配、细节优化、机器兼容问题(可自行下载体验:专业版下载安装)。

RainbowChat可能是市面上提供im即时通讯聊天源码的,唯一一款同时支持TCP、UDP两种通信协议的IM产品(通信层基于开源IM聊天框架 MobileIMSDK 实现)。

v7.0 版更新内容

此版更新内容更多历史更新日志):

  • 1)[新增] 新增了支持从相册中选取视频并发送;
  • 2)[bug] 解决了代码中设置聊天界面中消息文字颜色无作用的问题;
  • 3)[bug] 解决了聊天消息列表中查看短视频后返回时,最后一行消息被输入框档住的问题;
  • 4)[bug] 解决了一处因后台任务未显式结束导致的潜在内存泄漏问题;
  • 5)[bug] 当处于群聊界面是,群主更新群名称时,不能直接刷新群聊界面当前的标题上群名称的最新显示;
  • 6)[优化] 登陆界面中,密码输入框增加了密文和明文切换显示功能;
  • 7)[优化] 解决了iOS16.4+系统上因UIAlertView兼容性导致的某些功能中确认事件不能执行的问题;
  • 8)[优化] 解决了从其它界面返回到注册界面的动画跳转时,原界面导航栏变成黑色块的问题;
  • 9)[优化] 解决了聊天界面下方的功能面板打开状态下,再点“+” 号会切换到文本输入,而不是取消功能面板显示的问题;
  • 10)[优化] 升级了图片选择库以适配最新的iOS系统;
  • 11)[优化] 解决了聊天界面中发送大文件后,会立即弹出软键盘并进入文字输入状态的问题;
  • 12)[优化] 查看图片界面中,长按弹出菜单效果UI美化;
  • 13)[优化] 重新优化了闪屏、登录、帮助、忘记密码、注册、注册成功、查找用户、邀请朋友共计8个界面的UI设计;
  • 14)[优化] 其它未提及的ui细节优化和美感提升。

此版部分界面更新(更多截图点此查看):

 

posted @ 2023-08-23 13:28 Jack Jiang 阅读(80) | 评论 (0)编辑 收藏

本文由vivo互联网技术An Peng分享,本文收录时有内容修订和重新排版。

1、引言

本文通过对分布式ID的3种应用场景、实现难点以及9种分布式ID的实现方式进行介绍,并对结合vivo业务场景特性下自研的鲁班分布式ID服务从系统架构、ID生成规则与部分实现源码进行分享,希望为本文的阅读者在分布式ID的方案选型或技术自研提供参考。

 

技术交流:

(本文已同步发布于:http://www.52im.net/thread-4378-1-1.html

2、专题目录

本文是“IM消息ID技术专题”系列文章的第 7 篇,专题总目录如下:

IM消息ID技术专题(一):微信的海量IM聊天消息序列号生成实践(算法原理篇)

IM消息ID技术专题(二):微信的海量IM聊天消息序列号生成实践(容灾方案篇)

IM消息ID技术专题(三):解密融云IM产品的聊天消息ID生成策略

IM消息ID技术专题(四):深度解密美团的分布式ID生成算法

IM消息ID技术专题(五):开源分布式ID生成器UidGenerator的技术实现

IM消息ID技术专题(六):深度解密滴滴的高性能ID生成器(Tinyid)

IM消息ID技术专题(七):深度解密vivo的自研分布式ID服务(鲁班)》(* 本文)

vivo技术团队分享的其它文章:

vivo的Electron技术栈选型、全方位实践总结

vivo直播系统中IM消息模块的架构实践

3、分布式ID的应用场景

3.1概述

随着系统的业务场景复杂化、架构方案的优化演进,我们在克服问题的过程中,也总会延伸出新的技术诉求。分布式ID也是诞生于这样的IT发展过程中。

在不同的关联模块内,我们需要一个全局唯一的ID来让模块既能并行地解耦运转,也能轻松地进行整合处理。

以下,首先让我们一起回顾这些典型的分布式ID场景。

3.2系统分库分表

随着系统的持续运作,常规的单库单表在支撑更高规模的数量级时,无论是在性能或稳定性上都已经难以为继,需要我们对目标逻辑数据表进行合理的物理拆分。

这些同一业务表数据的拆分,需要有一套完整的 ID生成方案来保证拆分后的各物理表中同一业务ID不相冲突,并能在后续的合并分析中可以方便快捷地计算。

以公司的营销系统的订单为例:当前不但以分销与零售的目标组织区别来进行分库存储,来实现多租户的数据隔离,并且会以订单的业务属性(订货单、退货单、调拔单等等)来进一步分拆订单数据。

具体是:

  • 1)在订单创建的时候,根据这些规则去构造全局唯一ID,创建订单单据并保存在对应的数据库中;
  • 2)在通过订单号查询时,通过ID的规则,快速路由到对应的库表中查询;
  • 3)在BI数仓的统计业务里,又需要汇总这些订单数据进行报表分析。

3.3系统多活部署

无论是面对着全球化的各国数据合规诉求,还是针对容灾高可用的架构设计,我们都会对同一套系统进行多活部署。

多活部署架构的各单元化服务,存储的单据(如订单/出入库单/支付单等)均带有部署区域属性的ID结构去构成全局唯一ID。

创建单据并保存在对应单元的数据库中,在前端根据单据号查询的场景,通过ID的规则,可快速路由到对应的单元区域进行查询。

对应多活部署架构的中心化服务,同步各单元的单据数据时,单据的ID是全局唯一,避免了汇聚数据时的ID冲突。

在公司的系统部署中,公共领域的 BPM 、待办、营销领域的系统都大范围地实施多活部署。

3.4链路跟踪技术

在微服务架构流行的大背景下,此类微服务的应用对比单体应用的调用链路会更长、更复杂,对问题的排查带来了挑战。

应对该场景的解决方案,是会在流量入口处产生全局唯一的TraceID,并在各微服务之间进行透传,进行流量染色与关联,后续通过该全局唯一的TraceID,可快速地查询与关联全链路的调用关系与状态,快速定位根因问题。

在公司的各式各样的监控系统、灰度管理平台、跨进程链路日志中,都会伴随着这么一个技术组件进行支撑服务。

4、分布式ID的核心难点

分布式ID的技术难点比较,这里我简单总结了一下。

最核心的技术难点主要是:

1)唯一性: 保持生成的ID全局唯一,在任何情况下也不会出现重复的值(如防止时间回拔,时钟周期问题);

2)高性能: ID的需求场景多,中心化生成组件后,需要高并发处理,以接近 0ms的响应大规模并发执行;

3)高可用: 作为ID的生产源头,需要100%可用,当接入的业务系统多的时候,很难调整出各方都可接受的停机发布窗口,只能接受无损发布;

4)易接入: 作为逻辑上简单的分布式ID要推广使用,必须强调开箱即用,容易上手;

5)规律性: 不同业务场景生成的ID有其特征,例如有固定的前后缀,固定的位数,这些都需要配置化管理。

5、分布式ID的常见方案

常用系统设计中主要有下图9种ID生成的方式:

以下是详细表格说明之:

上面这些ID算法里,最知名是Twitter的雪花算法(Snowflake)。

Snowflake的核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 ID。

这 64 个 bit 中,其中 1 个 bit 是不用的,然后用其中的 41 bit 作为毫秒数,用 10 bit 作为工作机器 ID,12 bit 作为序列号。

SnowFlake的ID构成:

▲ 图片引用自《深度解密美团的分布式ID生成算法 - 美团为什么不直接用Snowflake算法?

SnowFlake的ID样本:

▲ 图片引用自《深度解密美团的分布式ID生成算法 - 美团为什么不直接用Snowflake算法?

6、自研分布式ID服务(鲁班)的方案

我们的系统跨越了公共、生产制造、营销、供应链、财经等多个领域。

我们在分布式ID诉求下还有如下特点:

  • 1)在业务场景上除了常规的Long类型ID,也需要支持“String类型”、“MixId类型”(后详述)等多种类型的ID生成,每一种类型也需要支持不同的长度的ID;
  • 2)在ID的构成规则上需要涵盖如操作类型、区域、代理等业务属性的标识;需要集中式的配置管理;
  • 3)在一些特定的业务上,基于安全的考虑,还需要在尾部加上随机数来保证ID不能被轻易猜测。

综合参考了业界优秀的开源组件与常用方案均不能满足,为了统一管理这类基础技术组件的诉求,我们选择基于公司业务场景自研一套分布式ID服务:鲁班分布式ID服务。

7、分布式ID服务鲁班的整体架构

鲁班的整体架构如下图所示:

鲁班的架构说明:

8、鲁班支持多种类型的ID规则

目前鲁班分布式ID服务共提供"Long类型"、“String类型”、“MixId类型”等三种主要类型的ID,相关ID构成规则与说明如下。

8.1Long类型

1)构成规则:

静态结构由以下三部分数据组成,组成部分共19位。如下所示。

* 固定部分(4位),由FixPart+ServerPart组成:

  • 1)FixPart(4位):由大区zone 1位/代理 agent 1位/项目 project 1位/应用 app 1位,组成的4位数字编码;
  • 2)ServerPart(4位):用于定义产生全局ID的服务器标识位,服务节点部署时动态分配。

* 动态部分DynPart(13位): System.currentTimeMillis() - 固定配置时间的TimeMillis (可满足使用100年)。

* 自增部分SelfIncreasePart(2位):用于在全局ID的客户端SDK内部自增部分,由客户端SDK控制,业务接入方无感知。共 2位组成。

2)降级机制:

主要自增部分在服务器获取初始值后,由客户端SDK维护,直到自增99后再次访问服务端获取下一轮新的ID以减少服务端交互频率,提升性能,服务端获取失败后抛出异常,接入业务侧需介入进行处理。

3)样例说明:

8.2String类型

1)构成规则:

静态结构由以下五部分数据组成,组成部分共25~27位。

* 固定部分操作位op+FixPart(9~11位):

  • 1)操作位op(2~4位):2~4位由业务方传入的业务类型标识字符;
  • 2)FixPart(7位):业务接入时申请获取,由大区zone 1位,代理 agent 2位,项目 project 2位,应用 app 2位组成。

* 服务器标识部分 ServerPart(1位): 用于定义产生全局ID的服务器标识位,服务节点部署时动态分配A~Z编码。

* 动态部分DynPart(9位):System.currentTimeMillis() - 固定配置时间的TimeMillis ,再转换为32进制字符串(可满足使用100年)。

* 自增部分SelfIncreasePart(3位):用于在全局ID的客户端SDK内部自增部分,由客户端SDK控制,业务接入方无感知。

* 随机部分secureRandomPart(3位):用于在全局ID的客户端SDK的随机部分,由SecureRandom随机生成3位0-9,A-Z字母数字组合的安全随机数,业务接入方无感知。

2)降级机制:

主要自增部分由客户端SDK内部维护,一般情况下只使用001–999 共999个全局ID。也就是每向服务器请求一次,都在客户端内可以自动维护999个唯一的全局ID。

特殊情况下在访问服务器连接出问题的时候,可以使用带字符的自增来做服务器降级处理,使用产生00A, 00B... 0A0, 0A1,0A2....ZZZ. 共有36 * 36 * 36 - 1000 (999纯数字,000不用)= 45656个降级使用的全局ID。

3)样例说明:

8.3MixId类型

1)构成规则:

静态结构由以下三部分数据组成,组成部分共17位。

* 固定部分FixPart(4~6位):

  • 1)操作位op(2~4位):2~4位由业务方传入的业务类型标识字符;
  • 2)FixPart(2位):业务接入时申请获取由代理 agent 2位组成。

* 动态部分DynPart(6位): 生成ID的时间,年(2位)月(2位)日(2位)。

* 自增部分SelfIncreasePart(7位):用于在全局ID的客户端SDK内部自增部分,由客户端SDK控制,业务接入方无感知。

2)降级机制:

无,每次ID产生均需到服务端请求获取,服务端获取失败后抛出异常,接入业务侧需介入进行处理。

3)样例说明:

9、鲁班的业务自定义ID规则实现

鲁班分布式ID服务内置“Long类型”,“String类型”,“MixId类型”等三种长度与规则固定的ID生成算法。除以上三种类型的ID生成算法外,业务侧往往有自定义ID长度与规则的场景诉求。

在鲁班分布式ID服务内置ID生成算法未能满足业务场景时,为了能在该场景快速支持业务,鲁班分布式ID服务提供了业务自定义接口并通过SPI机制在服务运行时动态加载,以实现业务自定义ID生成算法场景的支持。

相关能力的实现设计与接入流程如下。

1)ID的构成部分主要分FixPart、DynPart、SelfIncreasePart三个部分。

2)鲁班分布式ID服务的客户端SDK提供 LuBanGlobalIDClient的接口与getGlobalId(...)/setFixPart(...)/setDynPart(...)/setSelfIncreasePart(...)等四个接口方法。

3)业务侧实现LuBanGlobalIDClient接口内的4个方法,通过SPI机制在业务侧服务进行加载,并向外暴露出HTTP或DUBBO协议的接口。

4)用户在鲁班分布式ID服务管理后台对自定义ID生成算法的类型名称与服务地址信息进行配置,并关联需要使用的AK接入信息。

5)业务侧使用时调用客户端SDK提供的LuBanGlobalIDClient的接口与getGlobalId方法,并传入ID生成算法类型与IdRequest入参对象,鲁班分布式ID服务接收请求后,动态识别与路由到对应ID生产算法的实现服务,并构建对象的ID返回给客户端,完成整个ID生成与获取的过程。

10、鲁班保证ID生成不重复的方案

众所周之,如何保证ID服务生成的ID不碰撞、不重复,是最基本的要求之一。

我们是这样做的:

11、鲁班的无状态无损管理

服务部署的环境在虚拟机上,ip是固定,常规的做法是在配置表里配置ip与机器码的绑定关系(这样在服务扩缩容的时候就需要人为介入操作,存在一定的遗漏配置风险,也带来了一定的运维成本)。

但在容器的部署场景,因为每次部署时IP均是动态变化的,以前通过配置表里ip与机器码的映射关系的配置实现方式显然不能满足运行在容器场景的诉求,故在服务端设计了通过心跳上报实现机器码动态分配的机制,实现服务端节点ip与机器码动态分配、绑定的能力,达成部署自动化与无损发布的目的。

相关流程如下:

需要注意的是:

服务端节点可能因为异常,非正常地退出,对于该场景,这里就需要有一个解绑的过程,当前实现是通过公司平台团队的分布式定时任务服务,检查持续5分钟(可配置)没有上报心跳的机器码分配节点进行数据库绑定信息清理的逻辑,重置相关机器码的位置供后续注册绑定使用。

12、鲁班的使用方接入SDK的设计

SDK设计主要以"接入快捷,使用简单"的原则进行设计。

1)接入时:

鲁班分布式ID服务提供了spring-starter包,应用只需再pom文件依赖该starter,在启动类里添加@EnableGlobalClient,并配置AK/SK等租户参数即可完成接入。

同时鲁班分布式ID服务提供Dubbo & Http的调用方式,通过在启动注解配置accessType为HTTP/DUBBO来确定,SDK自动加载相关依赖。

2)使用时:

根据"Long"、"String"、"MixId"等三种id类型分别提供GlobalIdLongClient、GlobalIdStringClient、GlobalIdMixIDClient等三个客户端对象,并封装了统一的入参RequestDTO对象,业务系统使用时只需构建对应Id类型的RequestDTO对象(支持链式构建),并调用对应id类型的客户端对象getGlobalID(GlobalBaseRequestDTO globalBaseRequestDTO)方法,即可完成ID的构建。

Long类型Id获取代码示例:

packagecom.vivo.it.demo.controller;

 

importcom.vivo.it.platform.luban.id.client.GlobalIdLongClient;

importcom.vivo.it.platform.luban.id.dto.GlobalLongIDRequestDTO;

importorg.springframework.beans.factory.annotation.Autowired;

importorg.springframework.web.bind.annotation.RequestMapping;

 

@RequestMapping("/globalId")

publicclassGlobalIdDemoController {

 

    @Autowired

    privateGlobalIdLongClient globalIdLongClient;

 

    @RequestMapping("/getLongId")

    publicString getLongId() {

        GlobalLongIDRequestDTO globalLongIDRequestDTO = GlobalLongIDRequestDTO.Builder()

                .setAgent("1") //代理,接入申请时确定

                .setZone("0") //大区,接入申请时确定

                .setApp("8") //应用,接入申请时确定

                .setProject("7") //项目,接入申请时确定

                .setIdNumber(2); //当次返回的id数量,只对getGlobalIDQueue有效,对getGlobalID(...)无效

        longlongId = globalIdLongClient.getGlobalID(globalLongIDRequestDTO);

        returnString.valueOf(longId);

    }

}

13、鲁班的关键运行性能优化场景

13.1内存使用优化

在项目上线初时,经常发生FGC,导致服务停顿,获取ID超时。

经过分析,鲁班分布式ID服务的服务端主要为内存敏感的应用,当高并发请求时,过多对象进入老年代从而触发FGC。

经过排查主要是JVM内存参数上线时是使用默认的,没有经过优化配置,JVM初始化的内存较少,高并发请求时JVM频繁触发内存重分配,相关的对象也流程老年代导致最终频繁发送FGC。

对于这个场景的优化思路主要是要相关内存对象在年轻代时就快速经过YGC回收,尽量少的对象进行老年代而引起FGC。

基于以上的思路主要做了以下的优化:

  • 1)增大JVM初始化内存(-Xms,容器场景里为-XX:InitialRAMPercentage);
  • 2)增大年轻代内存(-Xmn);
  • 3)优化代码,减少代码里临时对象的复制与创建。

13.2锁颗粒度优化

客户端SDK再自增值使用完或一定时间后会向服务端请求新的id生成,这个时候需要保证该次请求在多线程并发时是只请求一次。

当前设计是基于用户申请ID的接入配置,组成为key,去获取对应key的对象锁,以减少同步代码块锁的粒度,避免不同接入配置去在并发去远程获取新的id时,锁粒度过大,造成线程的阻塞,从而提升在高并发场景下的性能。

14、应用现状

当前鲁班分布式ID服务日均ID生成量亿级,平均RT在0~1ms内,单节点可支持 万级QPS,已全面应用在公司IT内部营销订单、支付单据、库存单据、履约单据、资产管理编码等多个领域的业务场景。

15、未来规划

在可用性方面,当前鲁班分布式ID服务仍对Redis、Mysql等外部DB组件有一定的依赖(如应用接入配置信息、MixId类型自增部分ID计数器),规划在该依赖极端宕机的场景下,鲁班分布式ID服务仍能有一些降级策略,为业务提供可用的服务。

同时基于业务场景的诉求,支持标准形式的雪花算法等ID类型。

16、参考资料

[1] 微信的海量IM聊天消息序列号生成实践(算法原理篇)

[2] 解密融云IM产品的聊天消息ID生成策略

[3] 深度解密美团的分布式ID生成算法

[4] 开源分布式ID生成器UidGenerator的技术实现

[5] 深度解密滴滴的高性能ID生成器(Tinyid)


(本文已同步发布于:http://www.52im.net/thread-4378-1-1.html

posted @ 2023-08-16 11:31 Jack Jiang 阅读(111) | 评论 (0)编辑 收藏

本文由腾讯技术工程师remyliu分享,原题“微信万亿数据仓库架构设计与实现”,本文收录时有内容修订和重新排版。

1、引言

没有足够的特征数据,安全策略将是“无根之木,无源之水”。

微信的安全数据特征仓库应运而生,并成为整个安全业务的特征数据存储中心,每天服务了万亿级的特征数据读写请求,为整个微信安全策略提供了可靠的数据支撑,是微信安全基石之所在。

然而,微信安全特征数据仓库不仅仅是一个存储中心,更是一个特征管理和数据质量管理的中心。

微信的安全数据特征仓库在演进过程中,一直致力于提升特征管理能力和数据质量保障,实现了特征的管理、共享、分析和数据质量检测等功能。

本文将介绍微信的安全数据特征仓库的背景起源、技术演进、当前的架构设计和实践,以及数据质量保证系统的实现。希望给中大型IM系统的安全数据特征仓库的设计带来启发。

 
 
技术交流:

(本文已同步发布于:http://www.52im.net/thread-4374-1-1.html

2、安全策略开发流程

安全业务的核心逻辑是在安全策略中实现的。整个的策略开发流程包括特征数据的收集,安全策略的编写实现,和策略的反馈评估(如下图所示)。

其中特征数据的收集是必不可少的环节,数据的质量将直接影响安全策略的效果。

特征数据收集主要包括:

  • 1)数据接入;
  • 2)特征的计算;
  • 3)特征的存储。

传统特征数据收集流程:

如上图所示:在数据仓库还未建立时,业务同学通过消费离线存储mmdata和tdw接入数据,通过Flink流式计算或者自定义模块对数据进行加工,计算出需要的特征,最终存储到自行维护的KV,然后在安全策略平台上编写安全策略,读取KV中的数据, 实现需要的安全逻辑。

3、为什么需要安全特征数据仓库

前面提到在还未建立数据仓库时,业务同学都按照自己的方式去存储计算出的特征,大多通过自行申请部署KV来存储(如下图中的架构):如A同学把部署一套KV集群,存储特征到KV表中,B同学把特征存储到同KV集群的不同表中,C同学又额外申请了另外一套KV集群存储。

传统安全后台(各业务特征分散存储):

这种特征的分散存储,导致业务同学只了解自己熟悉的特征,难以交流和共享,特征缺乏统一的管理,数据质量难以保证,不同的存储方式,也导致特征访问接口的混乱,业务系统的可靠性也难以保证。

针对上述的问题:我们希望把所有业务的特征,按统一的规范,建立统一的存储,方便特征的共享、管理和维护、并建立数据质量保障体系, 为策略提供可靠的数据。所以我们需要开发数据仓库。

问题和目标:

4、安全业务的后台架构

当前,我们已经把所有的安全策略统一到安全策略平台进行开发和管理,特征数据的接入和计算统一到了Flink实时计算平台和特征平台。

数据仓库作为承上启下的部分,是整个业务体系中不可或缺的部分。

总结一下它作用就是:

  • 1)对上为在安全策略平台上的安全策略提供了数据读写;
  • 2)对下为实时计算平台和特征平台计算输出的特征提供了存储。

安全业务后台架构:

5、安全特征数据仓库的存储选型

微信的安全业务特征数据主要有2种类型:

  • 1)离线特征:用来满足离线计算数据导入线上实时使用的需求(通常特征离线计算,定期的批量后台上线,提供在线读,但不支持实时写入);
  • 2)实时特征:用来满足实时的在线读写需求。

微信内部有多种非常成熟稳定的自研KV:实时读写KV(简称实时KV)、离线写实时读KV(简称离线KV)、***KV等等,这些KV已经在多个业务被验证,有非常好的性能和可靠性,有团队做长期的维护,为此数据仓库的底层存储采用了微信自研的KV。

微信自研的KV主要特点如下:

具体就是:

  • 1)离线KV适合离线特征要求的场景:拥有非常好的读性能,并且提供了版本管理功能,在处理有问题数据时可以非常方便的可以回退版本,采用这种KV存储时,value一般是protobuf对象,新增特征时可以在pb中增加字段;
  • 2)实时KV适合实时特征的场景:在线实时读写性能优秀,而且支持数据过期淘汰,该KV提供了类MySQL表的概念,KV表定义类似于一个MySQL表,而每一个安全业务特征刚好可以用表的一个字段表示。

6、数据仓库的架构设计和演进

6.1统一存储统一接口

数据仓库第一个版本,针对特征存储分散访问接口混乱问题,首先部署了公共的实时KV/离线KV集群,并实现了一个接入层。新增特征和历史特征放到公共的KV存储集群,并且在接入层屏蔽了底层KV的细节,提供了统一的读写特征的接口。

数据仓库架构1.0版:

接入层支持任意多个KV集群,支持多个表,为屏蔽KV的细节,接入层为每个特征分配唯一的标识<sceneid, columnid>,读写特征数据使用唯一标识进行,不需要关注KV类型和KV表ID,方便业务的接入使用。

统一接口:

接入层还实现配置管理、参数校验、模块校验、权限校验、流水上报、PV统计等功能。

6.2读写分离和多IDC同步

1)读写分离:数据仓库的读请求量远远多于实时写入量,为了提高性能,减少读写之间的相互影响,接入层做了读写分离,将读和写接口拆分到两个模块。

2)数据多IDC同步:数据仓库和业务都采用的是多IDC部署,为了不降低查询性能,不希望业务跨IDC访问存储,所以底层的KV也是多IDC部署。这里就带来一个问题,特征数据如何在多IDC的KV之间进行同步? 例如业务在上海写入一个特征,希望在深圳也能读到这个特征。

这里按特征类型进行分类处理:

  • 1)离线特征数据同步:离线特征数据上线流程是通过离线计算在文件系统中生成一个文件,然后将文件导入到离线KV, 而离线KV支持多个IDC共享同一份数据,数据文件只需要生成一份,所有IDC的离线KV拉取同一个文件,新数据最终能同步到所有IDC上;
  • 2)实时特征数据同步:实时特征的同步采用微信自研的分布式队列组件,该组件提供了高可靠、高可用、高吞吐、低延时的数据消息队列服务。数据仓库写接入模块在写入数据时,同时将数据写一份到分布式队列,使用队列做跨IDC的数据同步,在其他IDC启动进程消费队列中的数据,写入到本IDC的实时KV,实现实时特征数据的同步。

数据仓库架构2.0版:

6.3异步写和替代分布式队列

1)异步写入:前一个版本中实时特征是同步写入,影响业务的性能,业务希望是异步写入。

2)替代分布式队列:前一个版本中分布式队列采用的是公共的集群,众多业务使用,出现过数据仓库受干扰影响特征数据同步。

为此:在数据仓库中新增一个异步消息队列模块写MQ,用于异步写入。和分布式队列相比,MQ更轻量,而且MQ我们可以自行维护,更可控。所以新架构中通过MQ实现实时特征的多IDC数据的同步,替代了分布式队列,保证数据同步不受其他业务影响。

数据仓库架构3.0版:

6.4运营系统

前面3个版本解决了特征存储分散、读写接口不统一、数据同步、读写性能问题,但是特征的上线依然采用的是配置发布上线的方式,效率依然低效。

更重要的是特征缺乏统一的管理,共享困难,难以满足业务的需求。

业务常常也有各种疑问:

为此数据仓库新增运营系统模块,实现了特征申请、特征上线、特征管理&分析、特征值查询/修改、特征数据质量管理等功能。

数据仓库架构4.0版:

1)特征申请:

用户不再需要手动的修改配置文件来新增特征,可直接通过WEB页面申请,填写必要的特征信息,通过通用审批系统进行审批。

2)特征上线:

用户不在需要手动的发布配置上线特征,无论是新增的实时特征还是离线特征,审批通过后将自动化的上线,提升体验和效率。

3)特征管理:

特征管理支持对特征meta信息进行查询和修改,包括特征所属的业务分类(索引)、特征类型、特征负责人、给特征打tag等等,业务可以方便的查询需要特征信息,避免重复的计算,方便各业务共享特征。

▲ 特征管理页面

4)特征分析:

追踪特征的原始数据来源、计算过程、数据流路径、最终的存储信息等等, 可以追踪特征完整生产流程。

▲ 特征分析页面

5)特征值查询&修改:运营系统支持在WEB页面查询特征值和修改特征值;

▲ 特征值查询页面

6)特征数据质量管理:保障数据质量, 下一章节详细讲述。

7、数据质量保障手段1:安全特征标准化

数据仓库主要通过两个方面来保障数据质量:特征的标准化和数据空跑系统。本节分享特征的标准化。

特征的标准化是保证数据仓库数据质量的手段之一,标准化是指对数据仓库中的特征进行规范化处理,使得特征能够达到一致性、可重复性等标准,从而提高数据的可靠性和准确性。

对于新增实时/离线特征:数据仓库制定了的特征规范文档,并按规范文档的要求,特征申请/管理页面必须正确的补充完整特征信息,如特征类型、业务分类等等,后台对每个特征都会进行校验,不符合规范的特征无法录入。

另外:数据仓库还提供了接入编程指导文档,并给出完整的C++编程实例,致力于提供标准化的编程最佳实践。

8、数据质量保障手段2:数据空跑系统

离线特征数据来自于业务离线计算在分布式文件系统中生成数据文件,然后将文件上线。

历史上曾因为生成的数据文件存在错误,存在错误的文件数据被上线到离线KV,导致策略出现故障。

为了保障离线特征数据的质量,数据仓库设计了一套空跑系统,在上线前对数据文件进行检查,避免存在问题的数据上线到现网。

数据空跑架构:

数据空跑架构如上图所示,离线特征数据的上线也纳入到了运营系统的管理中。

整个的空跑流程如下。

1)业务发起数据上线:运营系统将数据上线到备用的离线KV表,也就是用于空跑的KV表;

2)打开空跑开关:按一定的比率采样现网的读请求,旁路到新增的读MQ模块,该模块读空跑表的数据,和当前现网做对比, 分析差异率。这里采用的动态采样, 如果表的PV高则采样率低,PV低则采样率高或者100%采样,避免请求量小的表无法进行空跑,而请求量大的表空跑流量太高又消耗太多资源。

3)计算和分析差异率:如果差异率超过了阈值,就自动的拦截数据上线,如果阈值检查通过,就继续后续的检查流程,最终自动上线数据文件到现网离线KV。

差异率示例会如下图(详细的展示了具体的差异细节):

离线特征数据上线完整流程:

完整的数据上线流程如上图所示:空跑差异检测通过后,需要检查数据文件完整性,防止文件被修改或者覆盖,最后数据再上线到现网数据仓库系统,通知业务数据上线成功。如果中间任何一个步骤出错将告警给业务负责人,提醒人工介入处理。

9、本文小结

微信后台安全特征数据仓库将分散的特征全部集中统一管理,提供统一的访问接口,标准化每个一个特征,建立了统一的规范。

并且在此基础保障了数据的质量,夯实了整个安全业务的基础,助力一站式的数据-策略开发,极大的提升了安全对抗的效率,实现了数据价值的最大化。

10、相关资料

[1] 探讨组合加密算法在IM中的应用

[2] IM聊天系统安全手段之通信连接层加密技术

[3] IM聊天系统安全手段之传输内容端到端加密技术

[4] 理论联系实际:一套典型的IM通信协议设计详解(含安全层设计)

[5] 微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解

[6] 移动端安全通信的利器——端到端加密(E2EE)技术详解

[7] 通俗易懂:一篇掌握即时通讯的消息传输安全原理

[8] 基于Netty的IM聊天加密技术学习:一文理清常见的加密概念、术语等

[9] 手把手教你为基于Netty的IM生成自签名SSL/TLS证书

11、微信团队的其它技术文章

IM全文检索技术专题(一):微信移动端的全文检索优化之路

IM全文检索技术专题(二):微信移动端的全文检索多音字问题解决方案

微信团队分享:iOS版微信的高性能通用key-value组件技术实践

微信团队分享:iOS版微信是如何防止特殊字符导致的炸群、APP崩溃的?

微信团队原创分享:iOS版微信的内存监控系统技术实践

iOS后台唤醒实战:微信收款到账语音提醒技术总结

微信团队分享:微信Android版小视频编码填过的那些坑

企业微信客户端中组织架构数据的同步更新方案优化实战

微信团队披露:微信界面卡死超级bug“15。。。。”的来龙去脉

微信后台基于时间序的海量数据冷热分级架构设计实践

微信团队原创分享:Android版微信的臃肿之困与模块化实践之路

微信后台团队:微信后台异步消息队列的优化升级实践分享

微信团队原创分享:微信客户端SQLite数据库损坏修复实践

微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解

微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)

iOS版微信安装包“减肥”实战记录

移动端IM实践:iOS版微信界面卡顿监测方案

微信“红包照片”背后的技术难题

移动端IM实践:iOS版微信小视频功能技术方案实录

移动端IM实践:Android版微信如何大幅提升交互性能(一)

移动端IM实践:实现Android版微信的智能心跳机制

IPv6技术详解:基本概念、应用现状、技术实践(上篇)

微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)

微信团队分享:Kotlin渐被认可,Android版微信的技术尝鲜之旅

社交软件红包技术解密(十一):解密微信红包随机算法(含代码实现)

微信团队分享:极致优化,iOS版微信编译速度3倍提升的实践总结

IM“扫一扫”功能很好做?看看微信“扫一扫识物”的完整技术实现

微信团队分享:微信直播聊天室单房间1500万在线的消息架构演进之路

企业微信的IM架构设计揭秘:消息模型、万人群、已读回执、消息撤回等

IM全文检索技术专题(四):微信iOS端的最新全文检索技术优化实践

微信团队分享:微信后台在海量并发请求下是如何做到不崩溃的

微信Windows端IM消息数据库的优化实践:查询慢、体积大、文件损坏等

(本文已同步发布于:http://www.52im.net/thread-4374-1-1.html

posted @ 2023-08-11 11:41 Jack Jiang 阅读(80) | 评论 (0)编辑 收藏

  • 关于MobileIMSDK

MobileIMSDK 是一套专门为移动端开发的开源IM即时通讯框架,超轻量级、高度提炼,一套API优雅支持UDP 、TCP 、WebSocket 三种协议,支持iOS、Android、H5、标准Java平台,服务端基于Netty编写。

工程开源地址是:

关于RainbowChat

► 详细产品介绍:http://www.52im.net/thread-19-1-1.html
► 版本更新记录:http://www.52im.net/thread-1217-1-1.html
► 全部运行截图:Android端iOS端
► 在线体验下载:专业版(TCP协议)专业版(UDP协议)      (关于 iOS 端,请:点此查看

 

RainbowChat是一套基于开源IM聊天框架 MobileIMSDK 的产品级移动端IM系统。RainbowChat源于真实运营的产品,解决了大量的屏幕适配、细节优化、机器兼容问题(可自行下载体验:专业版下载安装)。

* RainbowChat可能是市面上提供im即时通讯聊天源码的,唯一一款同时支持TCP、UDP两种通信协议的IM产品(通信层基于开源IM聊天框架  MobileIMSDK 实现)。

v9.0 版更新内容

此版更新内容更多历史更新日志):

(1)Android端主要更新内容适配最新Android系统等多项升级和优化】:

  • 1)[升级] 提升targetSdkVersion至33;
  • 2)[升级] 适配最新Andriod 13+系统的动态权限申请逻辑;
  • 3)[升级] 解决了Android13+系统全面屏手机上,APP下方出现大约15dp的黑色空白问题;
  • 4)[升级] 解决了Android13+手机上无法显示Notification通知的问题(Android13新增了通知权限,需动态申请后才能显示);
  • 5)[优化] 重新优化了闪屏、登录、帮助、忘记密码、注册、注册成功、查找用户、实时语音、实时视频等共计13个界面的UI设计;
  • 6)[优化] 其它未提及的ui细节优化和美感提升。
  • 7)[bug] 解决了从好友列表中打开群聊界面,不显示“返回”按钮的问题。
  • 8)[bug] 解决了当处于群聊界面时,群主更新群名称时,不能同步刷新群聊界面标题上的群名称显示。

(2)服务端主要更新内容:

  • 1)[优化] 解决了桥接模式下与最新rabbitmq库不兼容从而断线重连不成功,导致MQ中消息堆积的问题:
  • 2)[优化] 解决了桥接模式下MQ断线自动恢复时未主动清理Chanel,导致Chanel越来越多的问题;

此版主要功能运行截图更多截图点此查看):

posted @ 2023-07-26 12:53 Jack Jiang 阅读(94) | 评论 (0)编辑 收藏

本文由网易云信李兴分享,原题“深度剖析“圈组”深度剖析“圈组”关系系统设计”,为了提升内容品质,本文收录时有修订。

1、引言

上篇《百万级成员实时社群技术实现(消息系统篇)》中,我们分享了云信“圈组”(“圈组”是云信的类Discord产品实现方案)消息系统的技术设计和实践。

本篇接上篇,将继续分享云信“圈组”的关系系统在技术架构上的设计和实现。希望带给你启发。

 
技术交流:

(本文已同步发布于:http://www.52im.net/thread-4333-1-1.html

2、系列文章

本文是系列文章中的第 3 篇:

3、作者介绍

李兴:网易云信资深服务端开发工程师,毕业于浙江大学,硕士毕业后加入网易,负责云信 IM等业务的服务器开发。专注于即时通讯以及相关中间件等技术。

4、“圈组”的关系业务特点

4.1概述

在互联网行业盛行一句话,技术是为业务服务的。具体到技术实践中,一个重要方面就是要面向业务特点设计技术方案。

因此,想要了解“圈组”的关系系统设计,就要首先了解“圈组”的关系业务特点。

4.2业务特点

“圈组”的关系业务特点是什么?

  • 1)其一:是关系复杂,即关系主体多、管理机制杂、联动耦合重;
  • 2)其二:是规模巨大,即成员数量可达百万量级、变更批量可达百万量级。

所谓关系复杂,具体来讲:首先是关系主体多。

在“圈组”业务中,关系主体包括:

  • 1)服务器:承载社群关系,负责社群成员关系维护;
  • 2)频道:从属于服务器,承载内容关系,负责内容互动关系维护;
  • 3)身份组:可从属于服务器或频道,承载身份权限关系,负责身份设定和权限配置;
  • 4)频道分组:从属于服务器,又关联一组频道,承载频道模版关系,负责分类频道和共享配置。

其次是:管理机制杂。

在“圈组”业务中,仅就成员管理机制而言:

  • 1)服务器成员采用邀请/申请机制;
  • 2)频道成员采用公开/私密模式+黑/白名单机制;
  • 3)身份组成员采用加入/移出机制;
  • 4)频道分组成员与频道成员采用同步机制。

最后是:联动耦合。

在“圈组”业务中,以频道成员维护为例:频道成员不仅受到公开/私密模式+黑/白名单配置变更的影响,而且会伴随服务器成员变更、身份组变更、身份组成员变更等做联动变更。

所谓规模巨大,具体来讲:

  • 1)一方面:成员数量可达百万量级(在“圈组”业务中,服务器成员数量可以达到数百万人);
  • 2)进一步:百万成员服务器下的频道和身份组,其成员数量也可以达到百万量级;
  • 3)另一面:是变更批量可达百万量级。

所谓变更批量可达百万量级,包括:删除百万成员的服务器/频道/身份组,增删频道/频道分组黑白名单中的百万成员身份组等。

从“圈组”关系业务的两大特点出发,可以发现:“圈组”关系是不同于群组关系的全新业务场景,将会面临全新的技术难点。

5、“圈组”关系系统的技术难点

5.1概述

技术难点主要有两个方面:

  • 1)其一:是多关系主体、多管理机制在层级结构下关联耦合导致的业务逻辑的复杂性;
  • 2)其二:是成员数量、变更批量规模巨大导致的业务处理在时间、空间、资源等开销上的复杂性。

5.2业务逻辑复杂性

1)首先“圈组”有多级结构:

包括服务器/频道二级结构、服务器/频道分组/频道三级结构等。

单个关系主体变更,不仅涉及自身的变更,而且涉及上下级关系主体的变更,可以说牵一发动全身。相比而言,群组是没有层级的,群组变更只要独善其身就好。

2)其次“圈组”有身份组:

一个身份组是一组有共同权限的服务器成员的集合,不同身份组的成员可以相互交叉,身份组会作为整体参与到成员管理中。

也就是说,成员变更不再只是个别成员(1-100人)的进入退出,将会出现整组成员(1-1000000人)的大进大出。相比而言,群组是没有身份组的,群组特殊成员包括群主、管理员等也都数量不多、互不重复。

3)最后“圈组”有多种成员管理机制:

服务器成员和身份组成员的管理机制与群组类似,频道成员和频道分组成员的管理机制却是全新模式。

频道分为公开和私密两种:

  • 1)公开模式默认允许所有服务器成员可见,但要排除黑名单身份组和黑名单成员;
  • 2)私密模式默认不许所有服务器成员可见,但要放开白名单身份组和白名单成员。

除了受到公开/私密模式+黑/白名单配置变更的影响,频道成员也受到所依赖的关系主体(服务器成员、身份组、身份组成员)变更的影响。进一步,频道成员还受到所同步的频道分组变更的影响。相比而言,群组成员的邀请/申请机制,可以说是小巫见大巫。

5.3业务处理复杂性

1)首先是成员数量规模巨大:

由于成员数量可达百万,整个成员列表的存储空间开销、网络传输开销,变得十分巨大,不论全量成员列表数据的服务器缓存,还是全量成员列表数据从服务器到客户端的同步,都将变得难以实现。

2)其次是变更批量规模巨大:

单次接口调用的关系变更,可能伴随百万规模的联动关系变更,这会导致巨大的处理时间开销、计算资源开销,不论所有变更同步完成处理,还是所有变更单机完成处理,都将变得难以实现。

3)最后是通知消息规模巨大:

关系系统不仅需要做关系变更的数据处理,而且需要通知变更结果到客户端。由于在“圈组”中各个关系主体的成员数量规模巨大,使得单个变更需要扩散为百万通知同时下发,所需计算资源开销、网络传输开销十分巨大。

相比而言,群组方案因为成员数量、变更批量规模有限,并不涉及这些技术难点。

从“圈组”关系系统的两个方面技术难点出发,可以发现:“圈组”关系系统面临不同于群组的全新技术难点,想要解决这些技术难点,需要创新的技术方案。

6、“圈组”的整体架构

“圈组”方案的整体架构:

上面展示了“圈组”方案的整体架构,可以看到“圈组”整体是一个分层架构。

从上到下看:

1)客户层:包括可供客户端集成的移动端、桌面端、跨平台 SDK,和可供服务器调用的 OpenAPI;

2)接入层:包括 LBS 服务、长连接服务和 API 网关,分别对应客户端 SDK 和用户服务器;

3)网络层:包括自研的全球实时传输网络 WE-CAN;

4)业务层:包括用于 SDK 业务处理的 App 服务和用于 OpenAPI 业务处理的 WebServer 服务;

5)服务层:划分有登录、消息、关系、身份组、支持等服务模块,每个服务模块包括有多个微服务或消费者;

6)基础设施层:包括系统所用的数据库和中间件。

7、“圈组”关系系统的架构

上图展示了“圈组”关系系统的技术架构。可以看到“圈组”关系系统遍及“圈组”架构的接入层、网络层、业务层和服务层。

从功能出发整体上分为三个部分:

  • 1)关系操作同步处理模块;
  • 2)关系事件异步处理模块;
  • 3)变更通知在线广播模块。

下面具体讨论三个方案要点的技术细节,包括频道成员关系管理、变更通知在线广播和关系数据云端检索。

8、关系系统技术实现1:频道成员关系管理

频道成员关系管理,是“圈组”中极具挑战性的问题。

频道成员涉及多关系主体、多管理机制、联动变更耦合严重,成员数量和变更批量规模巨大,可以说是“圈组”关系业务的典型代表。

频道成员关系管理在业务逻辑和业务处理两方面的复杂性可想而知。

针对频道成员关系管理问题,“圈组”设计了两大机制加以解决。

包括:

  • 1)终态维护与过渡计算相结合机制;
  • 2)事件按序异步并行处理机制。

终态维护与过渡计算相结合机制,具体来讲:频道成员关系数据最终被维护在持久化数据库中,并在频道成员没有变更的终态阶段,直接支持频道成员数据的查询需求。当频道成员发生变更时,由于变更逻辑和变更处理两方面的复杂性,完成关系变更需要一段时间,称之为过渡阶段。

在过渡阶段,数据库持久化的频道成员表数据是不完全准确的,无法直接支持频道成员数据的查询需求。此时转为由频道成员配置元数据直接计算频道成员以支持查询需求。因为频道成员配置元数据的变更是同步处理的,所以在过渡阶段由频道成员配置元数据直接计算频道成员可以保证查询准确性。通过将频道成员关系管理分为终态和过渡两个阶段,并在不同阶段采用不同频道成员查询方案,不仅解决了单纯由计算获取频道成员资源开销大的问题,而且解决了频道成员变更延迟导致由数据库获取频道成员结果不准确的问题。

除了频道成员的获取查询问题,频道成员的变更处理也很重要。

事件按序异步并行处理机制,就是用于解决频道成员的变更处理问题:

  • 1)其一:通过将影响频道成员关系的变更操作分层级、系统化定义为变更事件,显著降低频道成员关系管理的业务逻辑复杂性;
  • 2)其二:通过 ID 哈希、分布式锁、事件版本号控制等保证变更事件的按序处理,有效避免事件处理乱序导致的持久化数据错误;
  • 3)其三:通过消息队列中转事件并在消费者上异步处理,有效解决联动变更批量过大导致接口调用阻塞的问题;
  • 4)其四:通过在单个事件处理中的多线程并行加速和本地缓存重用加速,显著缩短频道成员关系变更的时间延迟。

9、关系系统技术实现2:变更通知在线广播

关系系统不仅需要做关系变更的数据处理,而且需要通知变更结果到客户端。

在百万量级的“圈组”关系中,每条关系变更通知,都会面临海量扩散的接收者。除了通知分发量激增,不同接收者对于通知接收的缓急差异也值得关注。

针对变更通知在线广播问题, 我们设计了两大机制:

  • 1)变更分类通知机制;
  • 2)数据通知拉取机制。

在变更分类通知机制中:一方面,根据相关人员在变更中的角色,划分为参与者和观察者分类做通知,即参与者一定通知,观察者按照订阅需求通知。其中参与者一般是变更中的少数关键人员,观察者则是除了参与者之外可以看到变更结果的其它人员。通过分类通知,不同接收者对于通知接收的缓急差异得到合理关注,变更通知的扩散规模也得到精准缩小。

另一方面,观察者按照订阅需求通知,可以充分发挥“圈组”的在线广播订阅模式的优势。所谓在线广播订阅模式,是指在用户登陆之后,需要订阅感兴趣的服务器/频道的通知,“圈组”系统会记录下这些订阅信息,当有新的通知时,“圈组”系统通过订阅关系而非成员列表 + 在线状态获取需要在线广播的用户列表,从而不再需要遍历服务器/频道的所有成员及其在线状态。通过采用在线广播订阅模式,不仅显著降低变更通知在线广播的计算开销和带宽开销,而且可以实现变更通知在线广播在长连接服务集群的并行加速和水平扩展。

变更通知的最终目的是将变更后的数据给到客户端:不同于群组,“圈组”并不将变更后的数据直接由通知带给客户端,而是采用通知客户端有变更再触发客户端拉取结果数据的机制。

究其原因,不同于群组将关系数据全量同步到客户端,“圈组”客户端不再存储关系数据的全量镜像,因此不再需要通过全量历史 + 增量变更的方式维护客户端上的关系数据全量镜像。

与此同时,订阅变更通知的观察者也并不是每时每刻都要关心变更的结果数据,关心某次变更结果数据的观察者相比订阅变更通知的观察者在数量上会少很多,因此,数据通知拉取机制会显著降低变更通知的资源开销。

另外,相比带变更数据通知,只通知有变更,便于直接合并相同类型的通知,而不用关心合并变更数据存在的时序、并发等问题,如此,数据通知拉取机制可以通过短时间内通知合并显著降低服务器在线广播开销和客户端通知接收开销。

10、关系系统技术实现3:关系数据云端检索

在“圈组”中,伴随关系规模的大幅增长,群组基于应用服务器全量查询关系数据或客户端全量同步关系数据实现精准查询和灵活排序的方案不再适用。

对此,“圈组”采用了关系数据云端检索的方案。

“圈组”关系数据云端检索方案可支持服务器、频道、成员等的检索能力。

从检索场景上分,包括:

  • 1)广场检索:用于检索感兴趣的服务器。可以根据名称、类别等多种维度检索。检索结果可以根据预定义字段(成员数量等)或自定义值(数据热度等)等进行排序;
  • 2)内部检索:用于检索用户可见的服务器、频道、成员等。可以根据名称、昵称等多种维度检索。检索结果可以根据预定义字段(创建时间等)或自定义值(数据热度等)等进行排序。

11、相关资料

[1] 一套亿级用户的IM架构技术干货(上篇):整体架构、服务拆分等

[2] 以微博类应用场景为例,总结海量社交系统的架构设计步骤

[3] IM开发技术学习:揭秘微信朋友圈这种信息推流背后的系统设计

[4] 直播系统聊天技术(四):百度直播的海量用户实时消息系统架构演进实践

[5] 喜马拉雅亿级用户量的离线消息推送系统架构设计实践

[6] 企业微信客户端中组织架构数据的同步更新方案优化实战

[7] 企业微信的IM架构设计揭秘:消息模型、万人群、已读回执、消息撤回等


(本文已同步发布于:http://www.52im.net/thread-4333-1-1.html

posted @ 2023-07-21 14:56 Jack Jiang 阅读(93) | 评论 (0)编辑 收藏

本文由网易云信资深服务器开发工程师曹佳俊分享,原题“深度剖析“圈组”消息系统设计 | “圈组”技术系列文章”,为了提升内容品质,本文有修订和删节。

1、引言

鉴于实时社群产品Discord在IM垂直应用领域的爆火,类似的需求越来越多,云信的“圈组”就是针对这种应用场景的技术产品。

“圈组”产品发布后获得了很大的关注,很多云信用户在接入SDK的同时对于“圈组”的底层技术细节和原理也非常关注,为此我们决定推出“圈组”相关的技术文章,分享云信在“圈组”技术设计上的一些思考和实践。

本文是序列文章的第2篇,将要分享的是云信的实时社群产品“圈组”(“圈组”云信的类Discord产品实现方案)的消息系统技术设计实践。

 
 技术交流:

(本文已同步发布于:http://www.52im.net/thread-4321-1-1.html)

2、系列文章

本文是系列文章中的第 2 篇:

3、作者介绍

曹佳俊:网易云信资深服务器开发工程师,毕业于中国科学院,硕士毕业后加入网易,负责云信 IM/RTC 信令等业务的服务器开发。专注于即时通讯、RTC 信令以及相关中间件等技术,是云信开源项目 Camellia 的作者。

4、“圈组”的技术特点

在介绍“圈组”的技术细节之前,我们先了解一下圈组的技术特点。

“圈组”产品最大的特点是什么?

  • 1)首先:是 server/channel 的二级结构;
  • 2)其次:是构建在二级结构之上的大规模社群(单个 server 数十万甚至上百万成员);
  • 3)以及:使用复杂的身份组系统来管理如此规模的社群组织和成员。

那么对于这样一个新颖的 IM 系统,在技术上应该如何实现呢?

5、“圈组”和传统IM群组的技术差异

5.1概述

一种简单的思路是改造已有的 IM 系统,对于“圈组”这样的类 Discord 社群,第一个思路是拓展我们的群组功能,猛一看在很多方面确实挺像的。

我们做了个简单的对比:

从上面的表格可以看到,“圈组”和群组最大的不同:

  • 1)是容量的区别;
  • 2)是二级结构。

其他的诸如身份组、个性化推送策略,似乎只要适配的做一下就可以了。

那么是不是只要想办法提升一下群组的容量,再在业务层封装一下二级结构就可以了呢?

答案显然是否定的,或者至少说基于群组去扩展不是一个很好的想法。

5.2二级结构的差异

首先是二级结构。

在类 Discord 的二级结构中,成员的管理在 server 层,而 channel 成员是继承自 server 的,而且在 channel 之上还有很多可见性的配置(我们的“圈组”提供了黑白名单机制,而Discord 则提供了查看频道权限)。

在这种机制之下,任何 server 层面的成员变动,都可能影响全部或者部分频道的成员列表。

面对这种复杂的结构,群组有两种思路去实现:

  • 1)一种是 N 个群,逻辑上隶属于同一个 server;
  • 2)一种是一个群映射为一个 server。

不管哪种方式,先不说消息投递这块的逻辑,仅成员管理上逻辑的耦合和交织的复杂性,足以劝退任何人。

5.3容量的差异

常规IM群组的容量一般只有数百,最多可以扩展到数千。

对于IM群组成员的管理,我们一般采取全量+增量同步相结合的方案,客户端和服务器映射到相同的群组镜像(群信息+群成员等)。此时很多操作,例如群成员的展示、检索,消息的艾特等,都可以基于纯客户端进行。

而“圈组”要求几十万甚至上百万的容量,显然客户端无法一次性获取到所有成员,如果你一次性加入多个 server,那成员的数量将更加膨胀。

因此在“圈组”这种大规模社群的设计中,很多逻辑都会转向云端,此时不管是 SDK 还是服务器,均需要修改原有的设计逻辑。

5.4消息规模差异

此外,大规模社群带来的是消息爆炸。

在原有的IM群组设计中,假设一个人同时加入了 1000 个群,那么这 1000 个群内的所有消息均会在第一时间下发给给客户端。

但是在一般的业务场景中,不会所有的群都同时活跃,假设这 1000 个群变成了 1000 个服务器/频道,作为一种社群组织,同时活跃的可能性将大大增加,而且每个服务器/频道的人数远远超过普通的群组,叠加之后带来的消息爆炸现象在原有的群组体系中将带来极大的压力。

压力包括多方面:

  • 1)首先是海量消息的存储压力;
  • 2)其次是海量消息在线广播/离线消息推送带来的带宽和服务器压力;
  • 3)以及客户端在面对大量消息冲击时如何有效地接受和合理的展示。

5.5小结

除了容量、二级结构、消息规模,包括身份组、成员管理、个性化推送策略等等都存在巨大差异。

是否真的适合在群组中添加这些复杂逻辑呢,强行绑定在一起会不会既没有一个好用的类 Discord 平台,也使得原始的群组功能繁杂,反而降低了易用性呢?

经过上面的一些分析,我们基本可以得出一个结论:在已有的群组基础上扩展来实现一个类 Discord 功能的社群,显然不是一个很好的思路。

那么还有其他“捷径”吗?

IM聊天室也是一个潜在的选项,聊天室的一大特点就是支持超大规模同时在线(参见《千万级实时直播弹幕的技术实践》),容量似乎已经不是问题,但是当考虑添加其他一些强社交关系的特性时(如成员、身份组等)就显得有点为难了,聊天室本身就是来去自如的一个开放空间,这个和圈组的产品本身定位互相冲突的。

因此基于聊天室扩展的方案也基本 pass 掉了。

6、“圈组”的技术难点

基于上述种种的思考和讨论,最终选择脱离已有 IM 体系,从零研发一套全新的社群方案“圈组”,“圈组”不是一个简单的 IM 功能,而是一套可以独立运行的 IM 系统。

经过上面的讨论,相信大家对“圈组”本身的技术特点和难点也有所理解。

可以归纳为以下几点:

  • 1)二级结构下成员无上限的社交关系系统设计;
  • 2)超大社群下消息系统设计;
  • 3)复杂高效的身份组系统设计;

7、“圈组”技术实现之整体架构  

“圈组”整体架构:

上面展示了“圈组”服务整体的架构。

可以看到整个“圈组”服务是一个分层的架构:

  • 1)首先是接入层,包括 LBS 服务和长链接服务器以及 API 网关,对应客户端 SDK 和用户服务器;
  • 2)后面是网络层,包括大网 WE-CAN 和协议路由服务;
  • 3)其次是服务层,划分了多个服务模块,每个模块都包括多个微服务;
  • 4)最后是基础设施。

8、“圈组”技术实现之消息系统架构

这其中和消息系统相关联的包括接入层、网络层、以及后端的登录/订阅/消息/检索等模块。

基本架构如下:

消息系统中第一个要讨论的点就是消息的存储和分发方式,包括在线广播、离线推送、历史消息三个维度。

下面几节我们将对消息系统中各模块分别展开介绍。

9、“圈组”消息系统技术实现1:在线广播

对于一般的IM群组来说,在线广播的一般过程是这样的:依次查询群组里的所有人的在线状态,如果在线,则将消息发送给对应的长链接服务器。

显然这种机制无法复制到“圈组”,因为在“圈组”的一个服务器里可能存在超过 100w 的人。

此外:IM聊天室的广播模式也不能直接复用,因为在聊天室架构中,每个长链接映射到一个聊天室,因此当你登录到某个聊天室的时候,你只会收到该聊天室的消息。而对于“圈组”来说,每个用户会同时加入多个服务器/频道,而且会同时收到多个服务器/频道的消息。

针对“圈组”的上述特点:我们设计了消息订阅模式,也就是用户登录之后,需要订阅感兴趣的相关服务器/频道,服务器会记录下这个订阅信息。当有新消息的时候,服务器通过订阅关系(而不是在线状态)查询到需要广播的列表,通过这种方式就不再需要遍历服务器/频道里的所有用户。

但是当一个服务器/频道里在线人数非常多的时候,这个订阅关系仍然是巨大的。

为此:我们设计了一种两层订阅模型,即所有的订阅关系会保存在长链接服务器上(QChatLink/QChatWebLink),同时长链接服务器会定时发送心跳给后端的订阅服务器,心跳信息相比原始的订阅信息会大大简化,比如长链接服务器上会记录账号 A 订阅了某个频道 A 的消息,如果有 1w 个账号,则有 1w 条订阅记录,而心跳信息里只会上报有 1w 个人订阅了某个频道 A 的消息,具体的账号列表则被精简掉了。当一条消息需要广播时,消息服务会访问订阅服务,获取到该服务器/频道被订阅的长链接服务器列表,并依次给该列表中的长链接服务器发送消息下发通知,长链接服务器收到通知后会根据订阅详情再广播给所有客户端。

此外:我们还提供了多种订阅类型,当你非常关心某个频道消息时(比如页面正停留在该频道),此时你可以订阅该频道的消息。对于其他频道,如果你仅仅需要知道该频道有多少条未读消息(或者有无未读消息),则可以选择订阅该频道的未读计数(或者未读状态),此时服务下发时仅会广播精简的消息体用于维护客户端未读计数,并且当未读计数达到一定阈值之后(比如 99+),服务器可以选择不再下发任何通知消息而不影响用户体验。

通过上文介绍的消息订阅模型,极大地提高了超大型的圈组频道/服务器消息在线广播的效率,降低了服务器压力。

除此之外:我们还设计了针对小型频道的特殊策略,对于小型频道,即使不订阅,服务器也会下发消息通知给频道里所有人,从而减轻端侧消息订阅模型的维护成本。针对消息订阅机制本身,后续我们也会根据不同的业务场景,提供更多一站式的策略来帮助降低接入成本,提升整体的易用性。

10、“圈组”消息系统技术实现2:离线推送

在强社交的场景下,离线消息推送对于维持用户粘性+提升产品体验有很大的作用。

从技术角度看的话,主要解决2个问题:

1)第一个是超大型服务器/频道的消息推送的效率问题;

2)另一个是提供足够丰富的推送策略来帮助 C 端用户,避免被过量的推送消息给打扰。

针对第一个问题,我们针对不同规模的服务器/频道采取了不同的策略:

  • 1)对于小型频道:采用类似于群组的消息推送模型;
  • 2)对于大型频道:对于每一条需要推送的消息,会根据目标用户的 ID 进行任务分片,多个节点并行操作,提高推送效率。

此外:分片会采用一致性策略,保证单个用户固定为某些节点,从而提高缓存命中效率。

针对第二个问题,推送策略可以用以下几句话来描述:

  • 1)既关注促活,又保证不打扰;
  • 2)大型 server 是游乐场,只推送与用户相关的重要消息(如 @消息);
  • 3)小型 server 是与朋友相处的小天地,支持消息的全部推送。

并且:未来用户还可以自定义消息的高低优先级,并搭配不同的推送配置(如不同的免打扰配置等),如下图所示。

11、“圈组”消息系统技术实现3:历史消息

历史消息的存储在“圈组”的场景中也需要一些特别的设计。

同样以传统IM群组为例,一般来说消息的存储方式有两种,写扩散和读扩散。在小型的IM群组或者多人会话中,写扩散模式可以简化设计,但是当群组规模扩大到一定程度(如万人群),读扩散就成了选择。

而对于“圈组”这种单个服务器可能上百万人的“群组”中,除了常规的读扩散之外,我们还设计了多级缓存的结构来应对海量的读请求。

基本的存储架构大致如下:

消息的存储主要包括两部分:

  • 1)一部分是消息本身;
  • 2)一部分是未读计数。

首先是写入:对于上述两者,我们都会使用中心化的缓存服务器来存储最近的数据,并使用异步+批量+聚合等手段,通过 MQ 异步落库,从而平衡写入效率(单条写入性能低)和写入读取延迟(异步写入有延迟)的问题,并且针对不同数据类型的特点,我们也选择了不同的存储方案(历史消息使用分布式时间序列数据库,未读计数使用分布式 k-v 数据库),最大化地提升消息存储和查询的性能和效率。

有写就有读,针对读取操作:

  • 1)所有最近的消息和未读计数均会存储在中心化缓存中,并通过先进先出和缓存过期等不同的策略来确保缓存中存储的永远是最新和最热的数据;
  • 2)对于消息 ID 和消息内容本身,中心化缓存中也会有不同的数据结构和过期策略,来平衡缓存命中率和缓存容量消耗;
  • 3)当缓存过期了,如果有关联的读写请求,将会触发缓存的重建,以保证缓存的命中率始终保持在较高水位;
  • 4)当有高频的读请求,还会触发热点 cache 的检测,并将一部分读请求下沉到各个计算节点的内存中,以应对突发流量的冲击。

上述针对“圈组”的特别设计,消息存储系统可以应对几十数百人的小型圈组频道,也可以从容应对上百万的超大型频道。

12、相关资料

[1] IM群聊消息究竟是存1份(即扩散读)还是存多份(即扩散写)?

[2] 网易云信技术分享:IM中的万人群聊技术方案实践总结

[3] 企业微信的IM架构设计揭秘:消息模型、万人群、已读回执、消息撤回等

[4] 融云IM技术分享:万人群聊消息投递方案的思考和实践

[5] 微信直播聊天室单房间1500万在线的消息架构演进之路

[6] 百万人在线的直播间实时聊天消息分发技术实践

[7] 千万级实时直播弹幕的技术实践

[8] 深度解密钉钉即时消息服务DTIM的技术设计

[9] 深度揭密RocketMQ在钉钉IM系统中的应用实践

[10] 一套亿级用户的IM架构技术干货(上篇):整体架构、服务拆分等

[11] 一套亿级用户的IM架构技术干货(下篇):可靠性、有序性、弱网优化等

[12] 从新手到专家:如何设计一套亿级消息量的分布式IM系统

(本文已同步发布于:http://www.52im.net/thread-4321-1-1.html

posted @ 2023-07-12 13:42 Jack Jiang 阅读(80) | 评论 (0)编辑 收藏

本文由腾讯产品体验设计师volihuang分享,原题“千万级增长,实时社交产品Discord拆解”,本文收录时有内容修订和大量排版优化。

1、引言

对于大多数人而言,对即时通讯IM应用的认知仍然停留在微信、QQ这类经典的即时通讯聊天场景。

实际上,如今的即时通讯技术已渗透到各种业态中,包括本系列文章将要分享的目前大热的Discord实时社群软件(Discord主要用于游戏社交),研究Discord软件包括技术实现上和产品定义上或许可以对你在其它业态中更好的应用即时通讯技术带来启发,也这是整理分系列文章的初衷。

本文为系列文章的首篇,文章内容不讨论Discord具体的技术实现,仅从其产品定义的角度上对Discord软件进行详尽和具体的介绍,希望能帮助你对Discord从产品形态上有较为完整的认知,也方便你阅读本系列文章的后续篇章。

 
 技术交流:

(本文已同步发布于:http://www.52im.net/thread-4300-1-1.html)

2、系列文章

本文是系列文章中的第 1 篇:

3、Discord是什么

3.1席卷游戏圈的社群

Discord是一家游戏实时聊天应用与社区,Discord从游戏语音、IM工具服务起家,随后转向直播平台,进而开设游戏商店的社区平台,成为游戏玩家在游戏中沟通协作的首选工具。Discord于2015年5月公开发行。

在 2018 年,它就已经席卷游戏圈,成了最受游戏玩家亲睐的「语音聊天工具」。在“英雄联盟”美服,几乎每局游戏开始前,都会有人发送 Discord 频道链接,邀请队友通过 Discord 沟通,而不是使用游戏内置的语音工具。

从语音聊天工具,到游戏玩家社区,Discord 似乎正在开创一种全新的互联网社会形态。它预示了一种比 reddit、Facebook 可能更理想的全新未来。

3.2从「工具」到「社区」

Discord 绝不是最「简单易用」的一个,但 Discord 却在思考如何从最底层优化产品,给到用户更多「可能性」.在疫情的大环境下,从2020年2月到7月,Discord的用户数量增加了47%,学习小组开始使用Discord;老师用它上课;朋友们用它来玩,就像平时放学后或周末一样。

3.3UI界面概览

4、Discord的发展历程

Discord相较于传统图文沟通模式的社群有着显著的优点:在Discord上社区建立者可以通过权限设置,轻松的进行用户细分,精准高效的传递信息;也可以进行社交媒体整合,为自己的其他社群进行引流。而Discord建立如此丰富的功能主要分为三个阶段来实现:

4.1第一阶段:游戏语音工具

核心增长点:极致的基础用户体验。

在工具阶段,Discord不断打磨全面超越竞品的基础体验,从界面审美、多端支持、延迟、降噪等等方面都处于市场领先地位。

通过极致的用户体验与因此收获的口碑传播,获取了第一批深度的种子用户。而这些用户逐渐围绕所玩的游戏形成了游戏社群。

4.2第二阶段:游戏社群

核心增长点:平台设计+能力开放+内容运营+用户质量。

在游戏社群阶段,Discord通过平台设计、能力开放、内容运营等方式加速了游戏社群的形成和壮大,游戏品类用户需求的溢出创造了更多的品类。

平台设计:完全免费设计、PC/Web/移动多端支持、免注册即可使用、无任何广告等,这些产品设计加速了用户的裂变;好友列表、加入服务器等沉淀的关系链继而让用户继续留存。Discord在产品设计中始终按照做一个平台的思路来设计,期望快速获得大量用户以形成网络效应。

能力开放:开放了较多的API能力,如支持游戏厂商接入语音sdk、支持同步Twitch直播状态、同步Steam游戏状态等等。这给用户和其他平台方提供强大的额外价值。

如音视频流可直接接入Discord,在服务器内就可以和好友一同观看Twitch/Youtube。如得知好友的游戏状态可以快速加入相同游戏一起开黑等。这也是平台设计的思路,开放能力接入第三方以获取赋能。

4.3第三阶段:全品类社群/社区

核心增长点:强大的管理能力(机器人开放平台/服务器权限/服务器模板…)。

Discord中服务器的管理能力非常丰富,通过设置不同的频道组和频道、设置身份权限、引入机器人等等手段,数十万人的社群也能够进行得有条不紊。

5、Discord的现状

现阶段,Discord 估计有 3 亿用户,其中包括 1.5 亿月活跃用户,平台上有 1900 万个服务器,涵盖游戏、投资、政治、动漫等领域。2020 年,Discord 每周有 670 万服务器处于活跃状态,基本上每周都有某个给定话题的对话讨论。2021 年,Discord 每周活跃服务器数据增长到了 1900 万。

来自移动产业数据平台 Apptopia 的消息显示,线上社区 App「Discord」的下载总量在近期已突破 5 亿次,同时应用内购营收总额突破 1 亿美元。

Discord 平台上单个日活跃用户(DAU)与平台的平均互动时长,是游戏直播平台 Twitch 的两倍,同时还是 Facebook Gaming、TikTok、Reddit 以及 Snap 等头部社交平台的两倍以上。

但是,即便在如此惊人的增长之后,Discord 似乎并没有太多商业化的动作。2020 年,Discord 的每用户平均收入 (ARPU) 仅为 1.30 美元,在公共社交媒体公司中排名非常靠后。


6、Discord平台机制介绍

6.1基本

Discord以其多样化的平台机制设定,为使用者提供了多种多样免费的功能。

它们是:

  • 1)以高音质、几乎零延迟、无限时间与尽可能多的朋友交谈;
  • 2)只需单击两次,即可将游戏直播带给服务器中的任何人,而且不会存在任何延迟;
  • 3) 使用单独的音量滑块一次观看多个流媒体;
  • 4)可以创建几乎无限量的文本聊天室,甚至可以追溯到几年前的档案;
  • 5)与朋友分享小文件;
  • 6)将机器人融入其中,可以向所有人广播音乐;
  • 7)Discord 支持视频流和屏幕截图等功能。

下面,我们详细介绍Discord中的功能设置。

6.2服务器机制

在 Discord 中有一种别于一般通讯软体之群组的群体聊天,称作服务器(类似社团),服务器拥有者可以在服务器中创造属于自己的社群。

例如:MINECRAFT在Discord的服务器,成员数已超过100w人,达到Discord目前设置的服务器上限。

MINECRAFT界面:

此外,在服务器搜索界面搜索MINECRAFT,可发现Discord上有6000+个MINECRAFT相关服务器,分布于社交、娱乐、同好、动画漫画、创作者等不同板块,绝大部分由玩家自发成立,在其中分享素材及想法。

6.3身份组机制

在 Discord 中可以建立非常多不同的身份组,使用者可以完全自订身分组的颜色、名称、权限、符号等等,身份组会直接影响使用者的名称颜色及用户列表的排序。

6.4频道机制

在伺服器中可以建立名为频道的聊天管道,分为语音、文字,其中的语音频道可以用来直播游戏与聊天等,频道可以设定与身份组整合各种权限,让 Discord 社群系统更加多样化。

文字方面:Discord 使用markdown语法,目的是对富文本一定程度的支持。

语音方面:Discord 使用opus音频格式,目的是压缩语音来降低延迟。

“哈利波特:魔法觉醒”的频道介绍列表:

6.5用户机制

每个 Discord 用户都有一个唯一的四位个人识别码,用户名后有一个"#"(例如ABCD#1234)。这使得多个用户能够拥有相同的用户名,并且用户可以很容易地找到朋友。

用户信息示意图:

6.6机器人

在 Discord 中所有使用者皆可以创立机器人,机器人主要是使用 Python 和 Java 编写,透过 Discord API 的语法扩充来编程。机器人可以发送讯息、图片、嵌入式讯息、嵌入式按钮、新增反应等,大致上与人类使用者权限无太大差异,不过在机器人的名称旁会有一个蓝色的 BOT 标志。机器人一样受到身份组权限的控管。

Topwar中的机器人消息及调用指令:

6.7整合

每个频道皆可以使用Webhook来抓取其他资讯,这使得在使用时甚至可以将Facebook、微博的贴文直接同步到Discord的频道中,另外频道也可以追踪另一个公告频道,来直接同步公告频道中的所有讯息。

6.8软件技术

尽管 Discord 的服务器由于其分布式特性无法匹配对应的传统硬件或虚拟服务器,不过其服务器和频道仍可类比于因特网中继聊天技术。用户可以在 Discord 上创建服务器并设定其他用户的加入条件。

Discord 的客户端使用Web技术构建在 Electron 框架上,这使得它可在多平台运行,既可在网页上运行,又可在个人计算机上作为应用程序运行。除了从 Discord 游戏商店下载和玩游戏为 Windows 独有之外,客户端的所有版本都支持相同的功能集(不包括与桌面音频的屏幕共享)。

Discord 是专门设计用于游戏互动的软件,因为它包括诸如低延迟、用户免费语音聊天服务器和专用服务器基础设施等功能。

6.9与游戏互联

在服务器和用户的层面上,Discord 允许用户连接到 twitch 或其他游戏账号。这种集成方式在一些应用程序中提供了独特的消息传递方法。

例如:如果用户使用自己的账号登录steam 玩游戏,Discord 便可以确定该用户正在玩该游戏。

6.10Nitro

虽然软件本身是免费的,但开发人员致力于研究如何将其商业化以营利,以Nitro计划的方式为对emoji和、贴图、个人化个人资料页面、语音及直播画质提升及文字字数限制进行付费使用。

7、Discord中的用户角色

Discord中的角色为用户提供特定权限。

例如:可以为主持人创建一个角色,并为该角色授予禁止用户和删除邮件的权限。 分配给该角色的任何用户都将继承这些权限。 使用角色可以使不必为每个用户分配权限。

要管理角色,请打开服务器设置,然后单击左侧的“角色”类别。 可以通过单击页面上“角色”标题侧面的小加按钮来添加新角色。 选择一个角色来管理权限。

有很长的权限列表,但重要的权限涉及通过创建新的渠道或角色来管理服务器的能力,通过禁止或删除邮件来管理用户,以及将用户移入和移出语音聊天。

还有一个管理员角色,它提供除服务器所有者特定的权限之外的所有权限(例如:删除服务器)。

8、Discord中的频道

服务器上的每个频道都按类别进行组织。 要创建新通道或类别,请右键单击通道窗格中的任意位置,然后单击“创建通道”或“创建类别”命令。

创建频道时,请为其命名并选择是应该是文字频道还是语音频道。 通道名称不能包含空格(键入空格只会创建连字符)或大写字母。

频道也有自己的频道特定权限,可以通过单击频道旁边的齿轮来访问这些权限。 这些权限默认与频道所属的类别同步,但如果更改它们,它们将保持这种状态,直到再次同步。

还可以将类别和频道设为私有。 当创建频道时,只需选择“私人频道”,然后启用希望能够访问该频道的角色。

如果只想向频道添加一些人,最好为该频道创建一个新角色,然后将用户添加到该角色。

下面我们讲介绍常见频道类型。

8.1)欢迎频道/规则频道:

欢迎频道一般包括服务器及游戏内容的大概说明、禁止的事项、频道发言规范等信息。可以由公告或文本频道设置而成。也可再次频道设置本地化相关选项(如语言)。

8.2)游戏活动公告频道组:

官方针对游戏内活动及社群相关活动的推宣,以公告频道的形式呈现。

8.3)游戏直播、其他社交媒体链接:

可以选择同步自身的twitter也可将自身所有媒体链接以消息的形式呈现,有助于游戏自身社交平台间的相互引流。

8.4)二创内容频道组:

通常包含玩家的绘画创作、视频创作、cosplay等,官方可在此频道中发布相应活动的信息并发放相应的活动奖励。

8.5)玩家公共讨论区频道组:

设置所有玩家都可参与的公共频道,为玩家提供交友、游戏内容交流甚至闲聊的空间。

8.6)语音讨论频道组:

为玩家建立可公共使用的语音频道,方便玩家与好友进行组队语音交流

8.7)娱乐频道组:

歌房:一起听歌的语音频道。

9、Discord中的机器人

除了聊天功能和社交架构之外,Discord 平台最引人注目的部分可能是其蓬勃发展的机器人生态系统。

在 2020 年的一篇博文中,Discord 宣布已经创建了超过 300 万个机器人,其中一些已经在数百万个服务器端上使用。

机器人举例:

  • 1)MEE6 是一个特别受欢迎的机器人应用,超过 1400 万服务器使用它来创建自定义欢迎消息、主动引导不良行为者、分配社区角色、并为积极参与社区活动的用户授予“XP”(“经验点”);
  • 2)ldleRPG 是一个提供更多创意服务的机器人应用,一旦它与服务器集成,社区成员就可以参与角色扮演游戏,这个游戏风格与《龙与地下城》相似,而且可以通过聊天命令参与。

从用户的角度来看,Discord 的机器人生态系统其实非常重要,因为可以扩展功能并增加游戏感。

而站在企业角度来看,机器人生态系统能从业务层面提供支撑,因为它允许开发人员在其应用程序接口(API)上进行构建。

10、Discord带来的启发

Discord背后的模式值得以社交的视角进行借鉴,辅助游戏端外社群运营。

1)首先:学会给用户创造一个新习惯,融入用户的生活场景,让用户对社区产生粘性。

Discord在提供给游戏玩家一个新的实时通话的社交平台的同时,其实是在给用户培养一个新的使用习惯,培养出来有社交互动需求的用户在玩游戏的时候,会的使用discord的习惯。

在培养用户的使用习惯以及粘性的这个过程中,需要团队专注于解决用户的核心需求,并且持续的提供技术支持。也就是要专注做好一个社交平台应该做的事情。

国内其实也有一个很好的例子。早年中国也有本土产出的用于服务游戏玩家“开黑”这定需求的社交软件,比方说,早年新浪上线的语音聊天产品UT,同期的在线群聊产品,以及后来的黑马YY语音。

2)其次:专注于解决用户的核心需求,找准定位,求同存异,保持用户的好感度。

从Discord的案例来说,它一开始的定位非常明确,就是小而精,针对于游戏群体的实时通话软件,然后在不断的完善功能的同时,扩大用户群体然后迅猛增长。

Discord专注于提升用户的体验并且保持用户社交的私密性,解决了解决用户的核心需求——网络实时社交。

11、相关资料

[1] 快速了解新一代跨平台桌面技术——Electron

[2] 盘点移动互联网时代的社交产品进化史(上篇):谁主沉浮

[3] 盘点移动互联网时代的社交产品进化史(下篇):大浪淘沙

[4] 中国互联网社交二十年:全民见证的互联网创业演义

[5] 别做梦了,社交产品哪有那么容易成功

[6] 同为IM社交产品中的王者,QQ与微信到底有什么区别

[7] 渐行渐远的人人网:十年亲历者的互联网社交产品复盘和反思

[8] 即时通讯创业必读:解密微信的产品定位、创新思维、设计法则等

[9] QQ的成功,远没有你想象的那么顺利和轻松

[10] 同为IM社交产品中的王者,QQ与微信到底有什么区别

[11] 还原真实的腾讯:从最不被看好,到即时通讯巨头的草根创业史

(本文已同步发布于:http://www.52im.net/thread-4300-1-1.html

posted @ 2023-07-07 12:13 Jack Jiang 阅读(108) | 评论 (0)编辑 收藏

本文由云信IM技术团队分享,原题“千万级在线直播弹幕方案”,本文有修订和改动。

1、引言

疫情期间,线上演唱会是一种很常见的直播娱乐形式,由于线下社交距离的限制,线上形式演唱会比以往更火爆,而对技术的要求也更高。

本文基于网易云信针对TFBOYS某场线上演唱会的技术支持,为你分享千万级在线用户量的直播系统中实时弹幕功能的技术实践,希望能带给你启发。

 

技术交流:

(本文已同步发布于:http://www.52im.net/thread-4299-1-1.html)

2、系列文章

本文是系列文章中的第 9 篇:

3、弹幕整体技术方案

本次的弹幕方案以IM聊天室技术为基础,提供了登录直播间、发送弹幕、礼物消息等能力。同时按照千万级在线广播的目标,为期设计了基于CDN的弹幕广播服务。

直播间收发实时消息(也就是弹幕、礼物)的主要流程如下:

  • 1)获取直播间接入地址;
  • 2)登录直播间;
  • 3)收发消息(弹幕、礼物)。

下面将围绕以上流程的三个阶段,在技术上分别阐述如何实现千万级在线直播实时弹幕的能力。

4、弹幕技术方案之获取直播间接入地址

为了提供稳定高可用的实时弹幕服务,需要通过GSLB(Global Server Load Balancing)服务给用户分配最佳的接入地址。

GSLB服务需要从以下几个维度综合考虑:

  • 1)用户网络类型;
  • 2)机房网络容量;
  • 3)服务器负载;
  • 4)成本。

1)用户网络类型和机房网络容量:

为了用户能够快速、稳定的登录直播间收发消息,一般要根据用户所在地理位置以及网络运营商类型综合考虑给用户分类接入服务器。

机房一般提供BGP网络、三线网络两种接入方案,分配服务根据用户IP地址分析用户的地域、运营商类型并分配最佳接入地址。

一般优先按运营商类型分配三线地址(例如电信用户分配电信接入地址),如果是小运营商或无法识别的IP地址则分配BGP地址,两种接入方式用户都可以获得稳定的网络环境。

2)服务器负载:

单台服务器能够承载的TCP长链接有限,尤其是在高并发进入直播间的情况下,握手协议需要完成链路加密工作,对系统的CPU资源消耗比较大,因此需要实现一套良好的均衡分配策略。

3)一套基于服务器负载均衡的分配策略:

长链接接入服务器周期性上报当前服务器负载到负载均衡服务集群,负载信息存储在共享缓存中,接入分配服务根据负载信息动态分配接入地址。

一般情况下用户请求直播间地址,地址分配服务会查询负载均衡服务(或者直接查询负载缓存),然后根据获取到的信息分配当前负载最低的服务器。

在千万级别的在线直播活动场景下,开播时大量用户并发进入直播间,分配服务可达50万到100万TPS,这么高的TPS下如果还用“一般分配”方案,负载均衡(缓存)服务的TPS和集群之间的机房网络带宽非常高,单台服务器亦可能因为负载信息滞后导致超负荷分配。

为解决机房内带宽和超负载分配的问题,我们对分配方案进行了优化:

  • 1)长链接服务器上报负载的周期从1秒调整到5毫秒,负载均衡服务器可以更实时的同步负载信息;
  • 2)“地址分配”服务不再按请求查询负载信息,而是开启单独的同步线程周期性(同样是5毫秒)同步负载数据,从而有效降低负责信息同步的TPS和网络开销;
  • 3)“地址分配”服务不在按最低负载分配,而是将服务接入地址按负载排序,单个接入地址分配一定次数后按顺序分配下一个接入地址(避免低负载服务器瞬间被打爆)。

在实际方案落地中,需要结合负载、用户网络类型、机房线路容量等因素综合分配。

5、弹幕技术方案之登录直播间

登录直播间主要有两项任务:

  • 1)握手;
  • 2)身份认证。

1)握手:

SDK建立TCP长链接后,首先向服务器发送握手协议,主要提供SDK版本、协议版本、支持的加密算法等信息,服务器根据SDK提供的信息选择合适的协议版本以及加密算法,建立安全的通信链路。

我们支持的非对称算法包括:RSA、SM2等算法。支持的对称加密算法包括:AES,SM4等(SM2、SM4为国密算法)。

非对称加密算法对CPU资源消耗非常高,为了提高性能一般可以考虑选择合适的密钥长度,另外针对Java平台建议考虑使用JNI技术提高非对称加密计算性能。

2)身份认证:

引言中提到的该次直播活动是在线付费直播,因此身份认证包含了账号认证和业务认证两部分,即用户必须使用正确的账号密码登录App,且必须付费购买直播门票才有权限观看直播。

为优化系统性能,实时弹幕服务将“地址分配和鉴权”服务进行了特殊优化:

鉴权中心提供用户进入直播间弹幕服务的身份鉴权策略配置。在该次直播活动中采用了动态Token的鉴权机制,即根据用户账号、登录时间、分配的接入地址以及鉴权中心按时间区间生成的“随机数以及对应的Token算法”动态计算鉴权Token。

用户打开直播App,首先完成账号鉴权。在进入直播间时通过业务中心完成直播付费身份认证和弹幕服务地址分配(同步获取到弹幕服务的动态鉴权token),最后根据接入地址登录弹幕服务,弹幕服务依据鉴权中心的策略校验Token正确性。

动态Token鉴权采用进程本地计算的方式。可以在不访问用户服务的情况下完成身份鉴权,在提高登录认证的性能同时有效的降低了业务成本。

6、弹幕技术方案之收发消息(弹幕、礼物)

实时收发消息是直播间的核心业务,主要分为弹幕和礼物两类:

  • 1)礼物因涉及付费等因素一般通过客户方业务服务器发送;
  • 2)弹幕消息则可以通过聊天室长链接发送。

在千万级直播间场景下,因消息量太高,因此需要从消息量、消息体大小、消息比例等多个方面优化,因此我们设计了一套基于优先级队列的弹幕服务。

首先:为了节约消息产生的带宽,在大型直播项目开始阶段,就需要对消息格式进行优化,充分精简消息体大小。例如将礼物消息展示相关的资源文件提前预加载到直播App中,礼物消息转化为业务编号,可极大的减少消息大小;

其次:针对上行消息设计流控机制。为了能全局控制上行消息体量,设计了逐级流控方案。上层级根据下层级能够支撑处理能力设计相对较粗粒度的本地流控机制。在弹幕反垃圾业务阶段,因需要全局控制消息量,因此采用分布式全局流控方案;弹幕广播阶段则根据业务广播需求再一次进行消息流控。

上行消息通过反垃圾监测后被投递到弹幕服务处理。基于优先级队列的弹幕服务首先按业务划分不同的消息队列,例如:系统广播、高优先级礼物、低优先级、弹幕,然后按队列分配消息比例,最后根据单位时间(1秒)内用户需要接收到的消息量计算各个队列应该投递的消息数量。在实际投递消息的过程中,若前一个队列消息量不足,可将剩余的消息数量叠加到下一个队列,以确保每一个周期都发送足够的消息给用户。

弹幕可通过长连接或CDN广播给其他用户。为了给用户提供极致的弹幕体验,充分发挥边缘加速的优势,在千万级在线直播场景下优先选择CDN方案(如下图所示)。

基于CDN广播弹幕有两种方案:

1)基于推流的方案:类似于直播视频推流技术,即将消息伪装成视频流的形式推送到CDN,直播App以订阅数据流的方式同步弹幕信息;

2)静态文件加速方案:即弹幕服务将不同队列中的消息组装成一个静态文件,直播App周期性的到CDN服务器下载弹幕静态文件。

相对来说:

  • 1)静态文件加速方案实现更简单但实时性不高(取决于弹幕同步的周期时长);
  • 2)推流的方案消息实时性更高,但实现相对复杂,且需要考虑到不同终端的兼容性。

实际项目中可根据场景和终端类型灵活选择不同的方案。

为了保障服务的可靠性,可考虑融合CDN的方案,即同时将消息推送到多家CDN厂商,并结合CDN厂商的容量比例以及网络延迟情况综合调度(例如基于权重的轮巡调度策略)。

7、弹幕稳定性设计之单元化部署

ChatLink和ChatServer采用单元化部署的方案,有以下优点:

  • 1)单元内依赖的核心服务单元之间相互独立,水平扩展能力好,且单元内服务故障不影响其他单元,可以有效避免整个服务不可用的问题;
  • 2)跨机房部署,避免单个机房容量不足,或单机房不可用问题;
  • 3)弹幕方案采用了单元无状态的设计理念,因此不需要考虑单元之间同步数据的问题。

单个直播间的“接入服务”和“弹幕服务”因需要全局控制未采用单元化部署方案,但是在实施阶段采用了跨机房部署的方案(包括依赖的存储资源、服务),可以避免单个机房故障导致服务不可用的问题。

8、弹幕稳定性设计之单点服务高可用

针对“接入服务”和“弹幕服务”,除了采用跨机房部署外,在服务设计上核心依赖的存储资源、服务,采用主备模式。

例如:心跳负载依赖的缓存服务,单个缓存实例本身高可用,但考虑到极端情况(例如缓存集群内超过一半的服务器宕机导致服务不可用),因此采用主备缓存集群方案,当主集群不可用后,业务主动切换到备用集群,可保障业务在5秒内恢复正常。

9、幕稳定性设计之系统监控与数据大盘

为了实时了解系统运行状态,在弹幕方案中实现了秒级数据大盘方案。

监控大盘围绕用户和消息主要展示以下信息:

  • 1)用户地域分布变化;
  • 2)上行消息量;
  • 3)广播消息量;
  • 4)机房出口带宽;
  • 5)CDN带宽;
  • 6)消息流控比例;
  • 7)端侧CDN弹幕同步指标(成功比例、延迟状况)。

为了达成秒级监控的目标,数据收集采用了“业务预聚合+数据中心合并”的实时计算方案。即业务服务直接在本地进程内聚合计算指标上报到数据中心,数据中心仅需要按时间窗口合并监控指标数据即可输出到监控大盘。

10、弹幕稳定性设计之故障与应急预案演练

为确保活动顺利完成,弹幕方案还进行了多次故障与应急预案演练措施。

具体包含两个方面。

1)预设故障演练:即针对高可用设计方案的故障演练,按预设有计划的制造故障,主要验证高可用方案是否生效。

2)随机故障演练:无计划的随机制造故障,主要用于检查应急预案、异常监控报警、数据大盘等应急监测机制是否生效。

11、相关资料

[1] 海量实时消息的视频直播系统架构演进之路(视频+PPT)

[2] 百万在线的美拍直播弹幕系统的实时推送技术实践之路

[3] 阿里电商IM消息平台,在群聊、直播场景下的技术实践

[4] 微信直播聊天室单房间1500万在线的消息架构演进之路

[5] 百度直播的海量用户实时消息系统架构演进实践

[6] 百万人在线的直播间实时聊天消息分发技术实践

[7] 直播间海量聊天消息的架构设计难点实践

[8] vivo直播系统中IM消息模块的架构实践

[9] 万人群聊消息投递方案的思考和实践

[10] IM中的万人群聊技术方案实践总结

(本文已同步发布于:http://www.52im.net/thread-4299-1-1.html

posted @ 2023-06-29 11:32 Jack Jiang 阅读(93) | 评论 (0)编辑 收藏

仅列出标题
共47页: First 上一页 7 8 9 10 11 12 13 14 15 下一页 Last 
Jack Jiang的 Mail: jb2011@163.com, 联系QQ: 413980957, 微信: hellojackjiang