写点什么

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

作者:JackJiang
  • 2024-02-29
    江苏
  • 本文字数:4688 字

    阅读完需:约 15 分钟

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

本文由 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

用户头像

JackJiang

关注

还未添加个人签名 2019-08-26 加入

开源IM框架MobileIMSDK、BeautyEye的作者。

评论

发布
暂无评论
抖音技术分享:飞鸽IM桌面端基于Rust语言进行重构的技术选型和实践总结_网络编程_JackJiang_InfoQ写作社区