关于即时通讯:抖音技术分享飞鸽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简化模型: ...