关于即时通讯:抖音技术分享飞鸽IM桌面端基于Rust语言进行重构的技术选型和实践总结

43次阅读

共计 5120 个字符,预计需要花费 13 分钟才能阅读完成。

本文由 ELab 团队公众号受权公布,原题《Rust 语言在 IM 客户端的实际》,来自抖音电商前端团队的分享,本文有订正和改变。

1、引言
本文将介绍飞鸽 IM 前端团队如何联合 Rust 对飞鸽客户端接待能力进行的技术晋升,一步步从概念验证、门路合成到分工开发,再到最初上线收益论证,并分享了其中遇到的技术挑战与经验总结等。本我的项目是一个长周期的简单我的项目,置信本我的项目落地的教训对其他同学及团队能有所借鉴。

技术交换:

  • 挪动端 IM 开发入门文章:《新手入门一篇就够:从零开发挪动端 IM》
  • 开源 IM 框架源码:https://github.com/JackJiang2011/MobileIMSDK(备用地址点此)
    (本文已同步公布于:http://www.52im.net/thread-4620-1-1.html)

2、技术背景
飞鸽是在抖音电商业务上面向商家和用户的聊天工具,其拉通售前、售中、售后渠道,为商家履约提供重要撑持。对于飞鸽桌面端 IM 而言,咱们会面临很多根底挑战,比方做好会话稳定性、操作流畅性、冷启动速度等,而在满足 98% 以上的用户需要且业务趋于稳定后,一些在冲刺后遗留的性能天花板问题裸露在咱们背后,其中 高并发接待 & 多开是两个重要的挑战,是旧账与难啃的硬骨头。

为何继续会有这些挑战存在?
1)历史技术选型,蕴含者老本、人力、效率等考量,飞鸽客户端应用的技术栈是 react + electron:* im sdk 与业务渲染代码都由 js 编写,im sdk 同时是 cpu 密集型 & io 密集型的组件,在高并发场景下,渲染频率也比拟高,业务与 sdk 互相抢占 cpu 资源与 io 资源,导致收发音讯慢、操作卡顿(高并发限度)。

* 因为 im sdk 运行在 webview 中,所以收发音讯依赖 webview 存活,故多开账号 = 多个 webview,内存老本线性增长。

2)im 页面在 web 层面屡次优化后已靠近架构下限,无奈基于现有架构做更多天花板的冲破。对于以上这些挑战,咱们给出的解法是:对现有架构进行调整,应用 Rust 语言对 im sdk 进行重写,彻底解除这一块的性能瓶颈!

3、为什么选 Rust 语言?
飞鸽 im sdk 是一个对运行稳定性要求高的组件,其工程量大、逻辑简单,对于异步个性应用十分频繁,其对于内存平安、线程平安有着比拟严格的要求。如果应用 C ++,作为老手并没有把握可能将简单的 IM SDK 少 bug 的编写下来(团队限度)。Rust 学习曲线尽管平缓,然而其为平安设计的各类语言个性、弱小的编译器,可能将新人编写代码的问题数降到最低(逻辑问题除外)。并且飞书团队提供了客户端的 rust 生态库,帮忙咱们解决很多的基建问题,所以这里应用 Rust 是相当适合的。

Rust 学习成长曲线:

4、飞鸽 IM 客户端历史架构的问题

如背景中所形容,历史架构存在这两个问题:
1)IM SDK 与 业务 JS 代码共用 Weview 资源,接待密集的时候,sdk 与业务,相互抢占 cpu 与 io 资源,导致容易卡顿、音讯提早;
2)多开的账号必须依赖 IM Webview 存活(否则无奈收到音讯),内存线性增长。

5、飞鸽 IM 客户端新架构与预期指标

具体是:
1)Rust 独立过程承当所有的 im sdk 的计算压力,能够大幅加重 js 线程压力,可晋升压力场景接待体验;
2)Rust im SDK 解除浏览器中的 IO 限度(如同域名并发数限度);3)解除 Webview 存活依赖,依附 rust 过程也可收音讯,为更多账号的多开能力提供了铺垫。

6、先用 Rust 进行技术可行性验证
为了验证揣测切实可行,咱们提前做了齐备的 POC 验证。在 POC 中,咱们针对“单过程单线程模型”、“多过程模型”、“多线程模型”,这三种模型搭建了 mvp demo,即繁难的客服聊天模型,并进行压力测试,并监测其内存、cpu 等指标。通过 POC,咱们得出的论断是:

具体就是:
1)rust 整体优于 js,计算占比越重,劣势越显著(低压时 cpu 差异能达到 3 倍以上);
2)架构选型上,rust 过程独立是最好的计划,稳定性更优、性能损耗相差较小。

7、新架构开始施行
路要一步步走,整个我的项目粗估下来会有上百的工作日,作为业务团队,咱们无奈在短期内投入大量的资源去做这个我的项目,所以须要一步一步拆解、验证、拿收益。团队内 native 开发资源无限,这件事件的进行也须要团队进行学习、成长。上面咱们将具体分享这个过程。

8、新架构施行阶段 1:Rust SDK 工程基建
造房子先得有一个地基 —— Rust 工程的根底建设,是 Native 业务的前置条件!桌面端同学牵头搭建了整个 RustSDK 地基,地基解决的问题如下图所示:

须要做的工作:
1)业务容器:有法则的组织代码构造,进行业务隔离、资源隔离;
2)跨过程调用封装:升高业务调用难度;
3)建设日志零碎、日志回捞:升高排查问题的难度;
4)构建跨平台异步执行环境:简化异步代码编写,底层封装,便于跨平台代码迁徙;
5)跨平台编译,跨平台集成;
6)… …

9、新架构施行阶段 2:IM 根底能力夯实
在领有一部分地基后,咱们开始针对 IM SDK 的根底能力进行实现和验证。因为只有实现根底能力验证之后,咱们才会有信念在新的架构上叠加更多的性能。

这阶段咱们关注以下指标(心愿其存在优化,至多不劣化):
1)长链在线率;
2)音讯发送成功率;
3)卡顿率;
4)Rust 过程解体率、无响应率。仅实现长链能力下沉,验证 & 晋升其稳固:

本阶段论证后果如下:
1)Rust Crash 率,达成预期;
2)Rust 无响应率 – 未达预期,可优化;
3)长链在线率 – 达成预期,然而存在优化空间;
4)卡顿率 – 不劣化 达成预期;
5)音讯发送成功率 – 不劣化,达成预期。
这阶段的工作是考验急躁的,因为这个阶段并不能带来实质性的用户体验晋升、也无奈拿到显著的晋升数据,只是作为两头阶段,它有存在的必要性。

这阶段后,在稳定性治理、根底能力验证、Rust 语言教训、指标制订合理性这几方面,咱们踩上了一个更牢固的台阶,更有信念去进行更简单的下一阶段。

10、新架构施行阶段 3:应用 Rust 实现 IM SDK 全副能力
夯实根底后,咱们开始发力冲刺,大刀阔斧的对 IM SDK 进行从新设计、实现、联调以及上线。此阶段要实现 im sdk 的全副能力、并对线上运行的 js im sdk 进行替换。因为飞鸽 im 对于通信模块的稳固水平要求是很高的,替换过程就像是在高速行驶的车辆上替换轮胎,如果呈现问题也容易导致大量的客服负面反馈。因而,新 rust sdk 的稳定性、异样问题时的兜底计划、灰度时的监控察看、对新增反馈的注意都很重要,放量过程会存在肯定精神压力。

工作内容大抵如下。
1)多实例的 Rust IM SDK 设计(商家单聊、群聊、平台客服)、Js -> Rust IMSDK 跨端调用协定设计:
a)剖析、拆解所有 Js Im SDK 至今具备的能力,并以贴合 Rust 的形式从新设计;
b)须要在协定设计中,尽可能的合并 & 简化 Js -> Rust 的调用,以缩小 IPC 通信老本。
2)开发:
a)Rust IM SDK 外围实现;
b)Rust\Js 适配同学严密单干,依据协定进行业务实现、业务适配;c)亲密沟通,发现问题及时纠偏;d)编写单测;

3)测试:
a)各类 IM 场景回归测试;
b)性能进行验证。
4)异样兜底计划实现:设计数据冗余,当 Rust 过程呈现解体、无响应、不可复原的网络谬误时,辨认并 fallback 到 web 版本,应用冗余数据疾速复原 im sdk 失常运行状态,确保用户体验。
5)稳当的上线计划 & 稳定性治理。
6)调用 & 适配优化,联合 Native 能力进一步性能优化。
7)后果回收。
8)其中各个步骤都会存在一些挑战,在后前面的内容会提到。调用简化模型:

IM Core 简化模型:

11、新架构施行阶段 4:基于稳固的 RustIM SDK 实现状态降级
最初的阶段,咱们基于欠缺的 Rust IM SDK 的能力进行状态的降级。本阶段正在进行中,实现后会做更多的分享。
1)多窗口革新:销毁后盾的多开账号,让多开账号数量冲破到 25 个。

2)音讯揭示、告诉流程革新。
3)音讯本地化能力:放慢音讯上屏。

12、技术挑战与实际总结
12.1 编程语言 & IM 畛域常识冲破
一个有战斗力的团队,肯定是继续学习、提高的。比方:
1)获取学习的纯正高兴:当沉迷在学习中,并感触到本人在提高的时候,会是一个高兴的状态;
2)逐渐克服小挑战,及时取得正反馈;
3)在共事中找到搭档和老师,询问与探讨:建设团队中的学习气氛。

12.2 长周期技术我的项目,如何持续保持信念?
比方:
1)Leader 与共事认可与反对 — 团队根底、价值观激励;
2)关注长期收益,训练本人提早满足感;
3)做好阶段性合成与验证,缩短单个周期(如本文的一二阶段拆解,可逐渐累积信念);
4)加强本身实力,做好问题把控,及时发现 & 解决问题。

12.3 高效单干
团队 Native 开发同学少,且各自并行业务需要,需正当的安顿开发路线,缩小总开发时长。

1)正当的设计开发并行路线,缩小串行依赖
2)协定与接口后行;
3)各同学负责其相近 & 善于的局部;
4)联调时缩短彼此间隔,高效沟通。

 12.4 保障用户体验的灰度上线
1)编写模块的衰弱自检,检测到异样时用最小的代价切换备用老计划。2)欠缺业务监控 & 技术指标监控:crash 率、无响应率、长链在线率、发消息成功率、申请成功率、卡顿率等。
3)对实在用户应用体验进行跟踪:
a)书反馈群组保护,及时取得用户反馈;
b)与商家客服放弃线下分割,获取一手体验状况。
4)放量节奏的把控:
a)大型改变能够先给白名单用户试用,收集反馈;
b)放出可能辨认问题的量,解决问题后再持续放量;
c)放量期间被动查问用户实时反馈数据,有问题及时解决。

 12.5 如何缩小 IPC 通信老本带来的开销
频率过高的 IPC 通信可能使得 CPU 优化事与愿违,因为老版本都运行在 Js 中,所以调用频率是没有节制的(循环读取数据也经常出现),必须要在设计上升高下来——升高业务 JS 线程的压力。以下措施能够将本场景通信老本升高 90% 以上。
1)更高效的数据协定 protobuf:相较于 json,数据更小、解析和序列化性能更高、跨语言生成代码工具。
2)Rust push to js:应用数据收集去重 + debounce 批量更新的策略,合并多个数据回调接口,缩小通信频率。
3)Js call rust(单次根底耗时 4ms):
a)适当缓存数据,不必每次都回源查问;
b)须要频繁调用的逻辑下沉 Rust,Rust 逻辑自欠缺。
12.6 后果回收:极其场景下的优化大盘数据体现不显著

 针对某种场景做的优化工作不容易在大盘数据中失去体现(尤其在灰度阶段),咱们应该针对非凡场景建设新指标。即编写策略,辨认并收集极其场景下的数据:为了掂量极其场景的的卡顿优化,建设了繁忙与卡顿指标,能够掂量出用户接待繁忙水平与卡顿率的关系,并且通过此指标将优化清晰的掂量进去。
12.7Rust SDK 的问题治理
具体是:
1)后期的问题不稳固,需更多信息辅助排查,日志尽量残缺;
2)与实在用户群体保持联系,可放慢问题验证、问题发现的过程;
3)须要建设便捷的日志回捞 & 日志剖析工具(帮忙疾速找到日志还原现场)。

13、新架构带来的收益
压力评测:

数据体现:

解读一下:
1)客服发送音讯,大盘端到端耗时升高 40%;
2)音讯发送成功率三个 9 -> 四个 9;
3)im 页面大盘卡顿率升高 15%;
4)密集接待场景,卡顿率升高 50%。全量至今,再无大量进线导致卡顿的反馈。回访历史反馈用户,皆无因大量接待导致的卡顿景象

14、相干文章
[1] 阿里技术分享:闲鱼 IM 基于 Flutter 的挪动端跨端革新实际
[2] IM 开发干货分享:有赞挪动端 IM 的组件化 SDK 架构设计实际
[3] IM 开发干货分享:我是如何解决大量离线音讯导致客户端卡顿的[4] 如约而至:微信自用的挪动端 IM 网络层跨平台组件库 Mars 已正式开源
[5] 从客户端的角度来谈谈挪动端 IM 的音讯可靠性和送达机制
[6] IM 开发干货分享:IM 客户端不同版本兼容运行的技术思路和实际总结
[7] IM 全文检索技术专题(四):微信 iOS 端的最新全文检索技术优化实际
[8] 从游击队到正规军(二):马蜂窝旅游网的 IM 客户端架构演进和实际总结
[9] IM 跨平台技术学习(九):全面解密新 QQ 桌面版的 Electron 内存优化实际
[10] IM 跨平台技术学习(五):融云基于 Electron 的 IM 跨平台 SDK 革新实际总结
[11] 抖音技术分享:抖音 Android 端手机功耗问题的全面剖析和具体优化实际
[12] 社交软件红包技术解密(十二):解密抖音春节红包背地的技术设计与实际

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

正文完
 0