本文由腾讯技术何金源分享,原题“不畏移山,手机QQ技术架构升级变迁史”,本文进行了排版和内容优化等。
1、引言
接上篇《总是被低估,从未被超越,揭秘QQ极致丝滑背后的硬核IM技术优化》,本文则将重点介绍手机 QQ 客户端技术架构升级背后的故事。
手机 QQ 经过20多年发展,功能不断增加,代码不断累积,架构已经变得越来越臃肿,影响到协作团队开发效率,对用户体验、质量稳定都有较大风险,因此手机 QQ 亟需技术架构的升级。但是对如此庞大的项目进行架构升级,在行业内也是少有的,手机 QQ 架构升级面临的困难和挑战都十分巨大,本文将围绕最新手机 QQ 客户端项目背景、项目历程、项目挑战、项目成果等方面进行深入介绍。
技术交流:
- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》
- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK(备用地址点此)
(本文已同步发布于:http://www.52im.net/thread-4658-1-1.html)
2、手机QQ的历史包袱
在过去20多年里,手机 QQ 从原来纯粹的即时通讯IM工具,成长为承载了空间、频道、短视频、超秀、增值服务等众多业务的平台。
随着业务越来越复杂,最初设计的技术架构变得越来越不适配,业务相互之间耦合越来越严重,时常会遇到改一个问题,牵扯出 N 个问题,问题改不动,代码债越积越多的情况,历史的包袱如同一座大山横在每一位手机 QQ 项目成员面前。
2020年,我们开始着手做架构升级。
鉴于手机 QQ 的业务复杂度、代码量级都非常大,评估下来架构升级的工作量大得惊人,于是我们采用分阶段、逐步演进的策略去进行架构升级。
整体回顾,手机 QQ 的架构升级时间线是这样的:
3、“解耦重构”架构设计
虽然历史包袱如同一座大山,但是手机 QQ 项目成员也有移山的意志和决心。
在2020年,手机 QQ 启动了名为“工业化实践”的技术架构升级项目,这标志着手机 QQ 工程首次系统性地进行业务边界划分、解耦和重构升级。
从上图可看出,旧架构虽然有模块化和插件化,但存在以下不足:
- 1)边界不清晰:主工程承载基础和大部分业务代码,导致基础和业务代码边界不清晰;
- 2)代码耦合紧:基础核心类持续膨胀、业务之间代码依赖不合理;
- 3)开发效率低:代码修改扩散造成 CR、解冲突、定位问题成本高,同时拖慢编译速度。
针对以上不足,对手机 QQ 工程重新设计了架构:
1)新架构按业务划分模块,业务模块之间是相互解耦的,业务模块之间通过接口和路由进行通信;
2)同时按层级设计划分,层级自上而下依赖,上层模块可依赖下层模块,但下层模块不能逆向依赖上层模块。
手 Q 客户端新架构:
新架构的主要收益:
- 1)模块更加内聚:新特性开发影响范围逐步收敛到模块内部,提升研发效率;
- 2)接口更加清晰:依赖数减少,可测性提升,更易于通过单元测试、接口测试保障代码逻辑正确性,提升产品质量。
4、“解耦重构”的实践历程
4.1概述
手机 QQ 工程各个业务之间的依赖非常严重,对它进行解耦重构不是一蹴而就的事情,需要按阶段制定目标,一步一步地优化。
通过整理,手机 QQ 工程解耦重构划分为以下三个阶段。
4.2阶段一(2020.11 - 2021.2)
基本完成约300万行核心代码的解耦,一共约30个基础模块和40个基础组件完成解耦,核心业务模块基本完成解耦。
开发新功能时,因为接口与服务实现是隔离的,通过接口依赖的代码不会再耦合严重。
4.3阶段二(2021.3 - 2021.6)
目标:业务模块继续解耦,建设防劣化机制。
成果:
- 1)API 代码占比与依赖数不增加;
- 2)完成防劣化机制搭建,在合入阶段拦住不合理修改;
- 3)完善动态化能力,优化插件与宿主间通信机制和发布效率。
4.4阶段三(2021.7 以后)
目标:进一步完善基础模块和组件化,实现子工程化。
成果:
- 1)完善基础模块和公共组件重构,建立基础模块发布组件流程;
- 2)对频道、小世界业务实现子工程化,独立编译运行。
5、“解耦重构”的技术收益
在重构基础上,梳理依赖关系,通过三个阶段改善模块化水平,提高编译速度和研发效率,流水线的编译耗时提升50%。
代码冲突方面也得到明显改善,对比重构前后数据,冲突文件数减少60%,冲突次数减少30%,大大提升开发效率。
6、手机QQ下一代架构:NT架构
在成功迈出改革的第一步之后,我们将注意力转向了手机 QQ 面临的版本碎片化问题。
不同端各自发展,形成了所谓的“烟囱式”结构,其中代码的复用率极低。这种结构带来了多端体验不一致、端内业务体验参差不齐以及每次版本更新时高昂的开发和维护成本等问题。
为了解决这些问题,并在提升用户体验、优化性能和提高研发效率方面实现突破,我们不得不深入思考。
正是这些迫切的需求和挑战促使我们启动了改革的第二步——推进手机 QQ NT 架构升级项目。
在 NT 架构设计之初,我们坚定认为不应该继续缝缝补补,而是应该采用最新且合理的技术理念,摒弃了简单的修补式方法。这次升级不仅是技术上的一次大刀阔斧的改造,更是一场深思熟虑的技术转型。
我们重视在不造成架构大规模动荡的前提下,制定了一条清晰、可行的实施路径。目标是以更少的人力投入实现更高的工作效率和成果,确保了升级过程中的高效和稳健。这种方法不仅保证了项目的顺利进行,也为未来的技术发展和迭代奠定了坚实的基础。
7、NT架构落地之难
由于手机 QQ 的历史悠久且拥有庞大的用户群,该项目在业务和用户层面都展现了巨大的复杂性。
具体来看,项目层面的挑战包括:
- 1)代码总量庞大:手机端代码近千万行,形成了一个技术上的庞然大物;
- 2)测试复杂性高:测试用例众多,功能繁杂,且存在部分文档缺失的情况;
- 3)依赖组件过时:项目中依赖了一些陈旧且缺乏维护的组件,以及大量无人维护的二进制库;
- 4)研发流程保障:在进行架构升级的同时,必须确保研发工作流程能够平稳过渡,以免影响到研发效率。
用户层面上的挑战则包括:
- 1)在长达一年以上的升级过程中,日常版本需要正常迭代;
- 2)用户本地数据量巨大,如超过 10G 的本地消息数据库;
- 3)项目需在技术优化的同时提升用户体验与活跃度,确保技术优化在用户端实现价值。
面对这些复杂度,项目的核心难点主要集中在以下三个方面。
1)海量功能项目的架构升级和统一:针对全终端、全功能和全项目团队的整体升级,确保架构升级过程中不能有任何缺失。手机 QQ 是在发展了20多年进行彻底重构,难度空前,没有资料可参考。
2)IM 全链路架构重写升级:解决陈年技术债,优化消息架构,平稳迁移用户历史数据,并提升消息性能。QQ 消息架构有陈年技术债,很多 QQ 历史版本里,没有统一的消息 ID 生成规则,没有统一的存储和索引方案,消息类型也是无序扩张。所以,既需要对IM全链路重写优化,同时在过程中,还需要平稳迁移用户历史数据,最终完成升级,保护用户数据、用户体验不受影响。
3)用户体验提升与活跃数据提升:逐步优化核心功能体验,不影响用户习惯,通过提升体验推动产品数据增长。代码的重写不能全盘一次性推倒重来。核心功能体验要保持,逐步优化,不能影响用户使用习惯。
这些挑战不仅说明了手机 QQ NT 架构升级项目的复杂性,也证明了我们在面对前所未有的技术难题时的决心。
8、NT架构设计
为了实现架构升级和统一,项目团队先用 C++ 开发了具备 QQ IM 核心功能的跨平台内核层:把 IM 核心业务逻辑(好友、群、频道等消息逻辑、资料与关系链逻辑、图片语音视频等富媒体收发逻辑、实时音视频逻辑等),QQ 通用组件(数据库、协议编解码、网络传输等),以及线程/网络/IO 等通用资源管理模块和操作系统封装部分,由原来的各平台原生语言实现,统一下沉到 C++ 跨平台层。
为了控制项目质量风险,NT 跨平台内核先接入用户量相对较少,对功能补齐紧迫度高的桌面端,完全用新架构重写桌面端。
在桌面端成功完成功能验证和质量测试之后,我们开始了向移动端的迁移工作,并顺利完成了 iOS 和安卓平台的集成。
当然,移动端的接入远远不像图中描述的这般容易,接下来将介绍其中的解决方案和主要过程。
9、 IM客户端全链路重写升级
在新的 NT 架构基础上,对 QQ 来说,最核心的技术升级,是 IM 全链路的升级。
IM 消息数据源复杂,历史包袱很重,升级过程的遇到的第一个难点就是数据转换及存量数据迁移到新版本问题。
比如:
- 1)老版本的 QQ,好友消息没有唯一标识字段,导入和去重影响大;
- 2)2012年以前的版本,群消息没有支持漫游,消息无唯一字段;
- 3)各平台消息数据格式不同,复杂度高,iOS 和 Android 分别有约200种消息类型;
- 4)富媒体(图片、视频、语音、文件)资源,存储的目录结构、命名都不同;
- 5)特殊消息,如结构化消息、Ark 消息、小灰条消息,需要做转换,完成业务的梳理和下架工作;
- 6)还有因为各种功能的变迁带来的遗留数据问题,如已经退出或者解散的群和讨论组等。
所以,首先需要做 IM 的精简。项目团队基于用户价值考虑,零基思维,完成消息格式统一,对消息和会话类型进行彻底精简,为 QQ 消息长治久安打下基础。
有了全端格式统一和类型精简的基础,开始用大小、性能、安全性综合最优方案设计跨平台统一的全新客户端 DB,然后再考虑旧 DB 的数据,如何平稳升级到新 DB。
移动端和桌面端不同,活跃用户全年在线,有些手机本地纯文本消息的 DB 文件超过10G,加上富媒体、文件等,总数据量超过100G,而且移动端又有存储空间小、功耗敏感、后台杀进程等多方面限制,需要设计出一套周密的升级策略,保护用户核心数据资产不丢失。
方案核心要点:
- 1)断点续导:移动端场景,进程随时可能被杀或退出。确保消息不丢失、不重复;
- 2)用户分级:跟进消息数据大小,用户分为三类,做不同的体验优化,减少对用户的影响;
- 3)优化发烫和耗电:限制导入速度,防止手机发烫。手机切后台后停止导入。对消息数据多的用户,引导用户设置在后台导入;
- 4)监控:做好各种导入异常上报监控,随时跟进用户反馈。
通过设计周密的升级策略,内部多轮推演,外部从百级开始放量,全方位监控,并用兜底策略保障不丢消息。最终结合监控数据和用户反馈数据,完成了全量用户的全量数据平稳迁移新 DB。
10、客户端核心功能优化提升
不仅是消息,在 NT 架构重写升级过程中,对 QQ 核心功能也一起做了更彻底的重构,手机 QQ 原生功能进行了大规模解耦,通用的部分进行优化并下沉为统一的 NT-Runtime 原生组件(NT 组件服务及框架层)。基于重构后的架构,也对性能进行全面优化。
首先是消息相关核心模块的优化。
消息逻辑下沉到 C++ 跨平台,也推动上层进行架构刷新。
以聊天窗口(AIO)为例:基于全新数据流架构 + 数据预加载 + UI 逻辑并行化的设计思路,完成单向数据流驱动与异步加载渲染,系统资源全力供给 AIO 消息列表,最终性能指标提升明显,AIO 内查看、跳转、滑动消息,顺畅丝滑。
核心技术优化方案:
- 1)采用基于单向数据流的 MVI 架构,实现业务解耦;
- 2)预加载和异步渲染,实现消息无缝滑动;
- 3)消息加载并行化,减少首屏和滑动时的加载时间;
- 4)消息动态加载、释放,优化内存占用。
- 5)200+业务组件懒加载,实现数据分层和按需加载。
其它 QQ 主场景,如消息列表页、消息与富媒体收发、图片视频查看等,也采用相同的路径进行优化,最终性能全面提升。
11、本文小结
在手机 QQ 超过20年的发展历程中,应用功能的不断扩展和代码量的持续增长积累了巨大的技术债务,给原有的客户端架构带来了沉重的负担。最新版手机QQ通过一系列的架构演变和技术升级,成功地实现了从臃肿不堪到模块化、高效、稳定的转变。
客户端架构由各端烟囱式架构逐步升级为多端跨平台复用的 NT 架构,降低多端维护人力成本,提升 QQ 全端开发效率,为 QQ 的持续发展和技术迭代打下了坚实的基础。
展望未来,QQ 将基于 NT 架构,在技术创新的道路上继续前行,不断进行架构优化和技术升级,为用户提供更加流畅稳定的产品体验。
12、相关资料
[1] 总是被低估,从未被超越,揭秘QQ极致丝滑背后的硬核IM技术优化
[2] 大型IM工程重构实践:企业微信Android端的重构之路
[4] 微信团队分享:详解iOS版微信视频号直播中因帧率异常导致的功耗问题
[5] 腾讯技术分享:Android版手机QQ的缓存监控与优化实践
[6] 腾讯技术分享:Android手Q的线程死锁监控系统技术实践
[9] 微信团队原创分享:Android版微信的臃肿之困与模块化实践之路
[10] 微信Windows端IM消息数据库的优化实践:查询慢、体积大、文件损坏等
[11] 微信团队分享:微信支付代码重构带来的移动端软件架构上的思考
[12] 微信客户端团队负责人技术访谈:如何着手客户端性能监控和优化
[13] 抖音技术分享:飞鸽IM桌面端基于Rust语言进行重构的技术选型和实践总结
[14] 阿里技术分享:闲鱼IM基于Flutter的移动端跨端改造实践
[15] QQ设计团队分享:新版 QQ 8.0 语音消息改版背后的功能设计思路
13、更多鹅厂技术文章汇总
- 微信朋友圈千亿访问量背后的技术挑战和实践总结
- 腾讯技术分享:腾讯是如何大幅降低带宽和网络流量的(图片压缩篇)
- IM全文检索技术专题(二):微信移动端的全文检索多音字问题解决方案
- 微信团队分享:iOS版微信的高性能通用key-value组件技术实践
- 微信团队分享:iOS版微信是如何防止特殊字符导致的炸群、APP崩溃的?
- 微信团队分享:微信Android版小视频编码填过的那些坑
- IM全文检索技术专题(一):微信移动端的全文检索优化之路
- 企业微信客户端中组织架构数据的同步更新方案优化实战
- 微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解
- 微信“红包照片”背后的技术难题
- 移动端IM实践:iOS版微信的多设备字体适配方案探讨
- 腾讯信鸽技术分享:百亿级实时消息推送的实战经验
- IPv6技术详解:基本概念、应用现状、技术实践(上篇)
- 腾讯技术分享:GIF动图技术详解及手机QQ动态表情压缩技术实践
- 微信团队分享:Kotlin渐被认可,Android版微信的技术尝鲜之旅
- 社交软件红包技术解密(一):全面解密QQ红包技术方案——架构、技术实现等
- 社交软件红包技术解密(四):微信红包系统是如何应对高并发的
- 社交软件红包技术解密(十):手Q客户端针对2020年春节红包的技术实践
- 微信团队分享:极致优化,iOS版微信编译速度3倍提升的实践总结
- IM“扫一扫”功能很好做?看看微信“扫一扫识物”的完整技术实现
- 微信团队分享:微信支付代码重构带来的移动端软件架构上的思考
- IM开发宝典:史上最全,微信各种功能参数和逻辑规则资料汇总
- 微信团队分享:微信直播聊天室单房间1500万在线的消息架构演进之路
- 企业微信的IM架构设计揭秘:消息模型、万人群、已读回执、消息撤回等
- IM全文检索技术专题(四):微信iOS端的最新全文检索技术优化实践
- 微信团队分享:微信后台在海量并发请求下是如何做到不崩溃的
- 微信Windows端IM消息数据库的优化实践:查询慢、体积大、文件损坏等
- 微信技术分享:揭秘微信后台安全特征数据仓库的架构设计
- IM跨平台技术学习(九):全面解密新QQ桌面版的Electron内存优化实践
- 企业微信针对百万级组织架构的客户端性能优化实践
- 揭秘企业微信是如何支持超大规模IM组织架构的——技术解读四维关系链
- 微信团队分享:详解iOS版微信视频号直播中因帧率异常导致的功耗问题
- 微信团队分享:微信后端海量数据查询从1000ms降到100ms的技术实践
- 大型IM工程重构实践:企业微信Android端的重构之路
- IM技术干货:假如你来设计微信的群聊,你该怎么设计?
- 微信团队分享:来看看微信十年前的IM消息收发架构,你做到了吗
- 长连接网关技术专题(十一):揭秘腾讯公网TGW网关系统的技术架构演进