1 歷史包袱
2 解耦重構(gòu)
3 NT 架構(gòu)升級(jí)
4 總結(jié)
本文是 QQ 25 周年技術(shù)巡禮系列的最終章,,在前兩篇文章中,,我們以《QQ 25年技術(shù)巡禮丨技術(shù)探索下的清新設(shè)計(jì),打造輕盈簡(jiǎn)約的 QQ9 》和《QQ 9“傻快傻快”的,?,!帶你看看背后的技術(shù)秘密》為題,介紹了QQ 團(tuán)隊(duì)在視覺(jué)打磨,、性能優(yōu)化背后的探索,,本文則將重點(diǎn)介紹手機(jī) QQ 技術(shù)架構(gòu)升級(jí)背后的技術(shù)故事。
手機(jī) QQ 經(jīng)過(guò)20多年發(fā)展,,功能不斷增加,,代碼不斷累積,架構(gòu)已經(jīng)變得越來(lái)越臃腫,,影響到協(xié)作團(tuán)隊(duì)開(kāi)發(fā)效率,,對(duì)用戶(hù)體驗(yàn)、質(zhì)量穩(wěn)定都有較大風(fēng)險(xiǎn),,因此手機(jī) QQ 亟需技術(shù)架構(gòu)的升級(jí),。但是對(duì)如此龐大的項(xiàng)目進(jìn)行架構(gòu)升級(jí),在行業(yè)內(nèi)也是少有的,,手機(jī) QQ 架構(gòu)升級(jí)面臨的困難和挑戰(zhàn)都十分巨大,,本文將圍繞項(xiàng)目背景、項(xiàng)目歷程,、項(xiàng)目挑戰(zhàn),、項(xiàng)目成果等方面進(jìn)行深入介紹。
01,、歷史包袱
在過(guò)去20多年里,,手機(jī) QQ 從原來(lái)純粹的即時(shí)通訊工具,成長(zhǎng)為承載了空間,、頻道,、短視頻、超秀,、增值服務(wù)等眾多業(yè)務(wù)的平臺(tái),。隨著業(yè)務(wù)越來(lái)越復(fù)雜,最初設(shè)計(jì)的技術(shù)架構(gòu)變得越來(lái)越不適配,,業(yè)務(wù)相互之間耦合越來(lái)越嚴(yán)重,,時(shí)常會(huì)遇到改一個(gè)問(wèn)題,,牽扯出 N 個(gè)問(wèn)題,問(wèn)題改不動(dòng),,代碼債越積越多的情況,,歷史的包袱如同一座大山橫在每一位手機(jī) QQ 項(xiàng)目成員面前。
2020年,,我們開(kāi)始著手做架構(gòu)升級(jí),。鑒于手機(jī) QQ 的業(yè)務(wù)復(fù)雜度、代碼量級(jí)都非常大,,評(píng)估下來(lái)架構(gòu)升級(jí)的工作量大得驚人,,于是我們采用分階段、逐步演進(jìn)的策略去進(jìn)行架構(gòu)升級(jí),。整體回顧,,手機(jī) QQ 的架構(gòu)升級(jí)時(shí)間線是這樣的:

02、解耦重構(gòu)
2.1 解耦重構(gòu)架構(gòu)設(shè)計(jì)
雖然歷史包袱如同一座大山,,但是手機(jī) QQ 項(xiàng)目成員也有移山的意志和決心,。在2020年,手機(jī) QQ 啟動(dòng)了名為“工業(yè)化實(shí)踐”的技術(shù)架構(gòu)升級(jí)項(xiàng)目,,這標(biāo)志著手機(jī) QQ 工程首次系統(tǒng)性地進(jìn)行業(yè)務(wù)邊界劃分,、解耦和重構(gòu)升級(jí)。
手 Q 舊架構(gòu)

從上圖可看出,,舊架構(gòu)雖然有模塊化和插件化,,但存在以下不足:
- 主工程承載基礎(chǔ)和大部分業(yè)務(wù)代碼,導(dǎo)致基礎(chǔ)和業(yè)務(wù)代碼邊界不清晰,。
- 基礎(chǔ)核心類(lèi)持續(xù)膨脹,、業(yè)務(wù)之間代碼依賴(lài)不合理。
- 開(kāi)發(fā)效率低:代碼修改擴(kuò)散造成 CR,、解沖突,、定位問(wèn)題成本高,同時(shí)拖慢編譯速度,。
針對(duì)以上不足,,對(duì)手機(jī) QQ 工程重新設(shè)計(jì)了架構(gòu)。新架構(gòu)按業(yè)務(wù)劃分模塊,,業(yè)務(wù)模塊之間是相互解耦的,,業(yè)務(wù)模塊之間通過(guò)接口和路由進(jìn)行通信。同時(shí)按層級(jí)設(shè)計(jì)劃分,,層級(jí)自上而下依賴(lài),,上層模塊可依賴(lài)下層模塊,但下層模塊不能逆向依賴(lài)上層模塊。
手 Q 新架構(gòu)

新架構(gòu)的主要收益:
- 模塊更加內(nèi)聚,,新特性開(kāi)發(fā)影響范圍逐步收斂到模塊內(nèi)部,,提升研發(fā)效率。
- 接口更加清晰,,依賴(lài)數(shù)減少,,可測(cè)性提升,更易于通過(guò)單元測(cè)試,、接口測(cè)試保障代碼邏輯正確性,,提升產(chǎn)品質(zhì)量。
2.2 解耦重構(gòu)的演進(jìn)歷程

手機(jī) QQ 工程各個(gè)業(yè)務(wù)之間的依賴(lài)非常嚴(yán)重,,對(duì)它進(jìn)行解耦重構(gòu)不是一蹴而就的事情,,需要按階段制定目標(biāo),,一步一步地優(yōu)化,。通過(guò)整理,手機(jī) QQ 工程解耦重構(gòu)劃分為三個(gè)階段:
- 階段一(2020.11 - 2021.2)


基本完成約300萬(wàn)行核心代碼的解耦,,一共約30個(gè)基礎(chǔ)模塊和40個(gè)基礎(chǔ)組件完成解耦,,核心業(yè)務(wù)模塊基本完成解耦。開(kāi)發(fā)新功能時(shí),,因?yàn)榻涌谂c服務(wù)實(shí)現(xiàn)是隔離的,,通過(guò)接口依賴(lài)的代碼不會(huì)再耦合嚴(yán)重。
- 階段二(2021.3 - 2021.6)
目標(biāo):業(yè)務(wù)模塊繼續(xù)解耦,,建設(shè)防劣化機(jī)制,。
成果:
- API 代碼占比與依賴(lài)數(shù)不增加。
- 完成防劣化機(jī)制搭建,,在合入階段攔住不合理修改,。
- 完善動(dòng)態(tài)化能力,優(yōu)化插件與宿主間通信機(jī)制和發(fā)布效率,。
- 階段三(2021.7 以后)
目標(biāo):進(jìn)一步完善基礎(chǔ)模塊和組件化,,實(shí)現(xiàn)子工程化。
成果:
- 完善基礎(chǔ)模塊和公共組件重構(gòu),,建立基礎(chǔ)模塊發(fā)布組件流程,。
- 對(duì)頻道、小世界業(yè)務(wù)實(shí)現(xiàn)子工程化,,獨(dú)立編譯運(yùn)行,。
2.3 解耦重構(gòu)收益
在重構(gòu)基礎(chǔ)上,梳理依賴(lài)關(guān)系,,通過(guò)三個(gè)階段改善模塊化水平,,提高編譯速度和研發(fā)效率,流水線的編譯耗時(shí)提升50%。代碼沖突方面也得到明顯改善,,對(duì)比重構(gòu)前后數(shù)據(jù),,沖突文件數(shù)減少60%,沖突次數(shù)減少30%,,大大提升開(kāi)發(fā)效率,。

03、NT 架構(gòu)升級(jí)
在成功邁出改革的第一步之后,,我們將注意力轉(zhuǎn)向了手機(jī) QQ 面臨的版本碎片化問(wèn)題,。不同端各自發(fā)展,形成了所謂的“煙囪式”結(jié)構(gòu),,其中代碼的復(fù)用率極低,。這種結(jié)構(gòu)帶來(lái)了多端體驗(yàn)不一致、端內(nèi)業(yè)務(wù)體驗(yàn)參差不齊以及每次版本更新時(shí)高昂的開(kāi)發(fā)和維護(hù)成本等問(wèn)題,。為了解決這些問(wèn)題,,并在提升用戶(hù)體驗(yàn)、優(yōu)化性能和提高研發(fā)效率方面實(shí)現(xiàn)突破,,我們不得不深入思考,。正是這些迫切的需求和挑戰(zhàn)促使我們啟動(dòng)了改革的第二步——推進(jìn)手機(jī) QQ NT 架構(gòu)升級(jí)項(xiàng)目。

在 NT 架構(gòu)設(shè)計(jì)之初,,我們堅(jiān)定認(rèn)為不應(yīng)該繼續(xù)縫縫補(bǔ)補(bǔ),,而是應(yīng)該采用最新且合理的技術(shù)理念,摒棄了簡(jiǎn)單的修補(bǔ)式方法,。這次升級(jí)不僅是技術(shù)上的一次大刀闊斧的改造,,更是一場(chǎng)深思熟慮的技術(shù)轉(zhuǎn)型。我們重視在不造成架構(gòu)大規(guī)模動(dòng)蕩的前提下,,制定了一條清晰,、可行的實(shí)施路徑。目標(biāo)是以更少的人力投入實(shí)現(xiàn)更高的工作效率和成果,,確保了升級(jí)過(guò)程中的高效和穩(wěn)健,。這種方法不僅保證了項(xiàng)目的順利進(jìn)行,也為未來(lái)的技術(shù)發(fā)展和迭代奠定了堅(jiān)實(shí)的基礎(chǔ),。
3.1 NT 架構(gòu)落地之難
由于手機(jī) QQ 的歷史悠久且擁有龐大的用戶(hù)群,,該項(xiàng)目在業(yè)務(wù)和用戶(hù)層面都展現(xiàn)了巨大的復(fù)雜性。具體來(lái)看,,項(xiàng)目層面的挑戰(zhàn)包括:
- 代碼量龐大:手機(jī)端代碼近千萬(wàn)行,,形成了一個(gè)技術(shù)上的龐然大物。
- 測(cè)試復(fù)雜性高:測(cè)試用例眾多,,功能繁雜,,且存在部分文檔缺失的情況,。
- 依賴(lài)組件過(guò)時(shí):項(xiàng)目中依賴(lài)了一些陳舊且缺乏維護(hù)的組件,以及大量無(wú)人維護(hù)的二進(jìn)制庫(kù),。
- 研發(fā)流程保障:在進(jìn)行架構(gòu)升級(jí)的同時(shí),,必須確保研發(fā)工作流程能夠平穩(wěn)過(guò)渡,以免影響到研發(fā)效率,。
用戶(hù)層面上的挑戰(zhàn)則包括:
- 在長(zhǎng)達(dá)一年以上的升級(jí)過(guò)程中,,日常版本需要正常迭代。
- 用戶(hù)本地?cái)?shù)據(jù)量巨大,,如超過(guò) 10G 的本地消息數(shù)據(jù)庫(kù),。
- 項(xiàng)目需在技術(shù)優(yōu)化的同時(shí)提升用戶(hù)體驗(yàn)與活躍度,確保技術(shù)優(yōu)化在用戶(hù)端實(shí)現(xiàn)價(jià)值,。
面對(duì)這些復(fù)雜度,,項(xiàng)目的核心難點(diǎn)主要集中在以下三個(gè)方面:
- 海量功能項(xiàng)目的架構(gòu)升級(jí)和統(tǒng)一:針對(duì)全終端、全功能和全項(xiàng)目團(tuán)隊(duì)的整體升級(jí),,確保架構(gòu)升級(jí)過(guò)程中不能有任何缺失,。手機(jī) QQ 是在發(fā)展了20多年進(jìn)行徹底重構(gòu),難度空前,,沒(méi)有資料可參考,。
- IM 全鏈路架構(gòu)重寫(xiě)升級(jí):解決陳年技術(shù)債,,優(yōu)化消息架構(gòu),,平穩(wěn)遷移用戶(hù)歷史數(shù)據(jù),并提升消息性能,。QQ 消息架構(gòu)有陳年技術(shù)債,,很多 QQ 歷史版本里,沒(méi)有統(tǒng)一的消息 ID 生成規(guī)則,,沒(méi)有統(tǒng)一的存儲(chǔ)和索引方案,,消息類(lèi)型也是無(wú)序擴(kuò)張。所以,,既需要對(duì)IM全鏈路重寫(xiě)優(yōu)化,,同時(shí)在過(guò)程中,還需要平穩(wěn)遷移用戶(hù)歷史數(shù)據(jù),,最終完成升級(jí),,保護(hù)用戶(hù)數(shù)據(jù)、用戶(hù)體驗(yàn)不受影響,。
- 用戶(hù)體驗(yàn)提升與活躍數(shù)據(jù)提升:逐步優(yōu)化核心功能體驗(yàn),,不影響用戶(hù)習(xí)慣,通過(guò)提升體驗(yàn)推動(dòng)產(chǎn)品數(shù)據(jù)增長(zhǎng),。代碼的重寫(xiě)不能全盤(pán)一次性推倒重來(lái),。核心功能體驗(yàn)要保持,逐步優(yōu)化,不能影響用戶(hù)使用習(xí)慣,。
這些挑戰(zhàn)不僅說(shuō)明了手機(jī) QQ NT 架構(gòu)升級(jí)項(xiàng)目的復(fù)雜性,,也證明了我們?cè)诿鎸?duì)前所未有的技術(shù)難題時(shí)的決心。
3.2 NT 架構(gòu)設(shè)計(jì)
為了實(shí)現(xiàn)架構(gòu)升級(jí)和統(tǒng)一,,項(xiàng)目團(tuán)隊(duì)先用 C++ 開(kāi)發(fā)了具備 QQ IM 核心功能的跨平臺(tái)內(nèi)核層:把 IM 核心業(yè)務(wù)邏輯(好友,、群、頻道等消息邏輯,、資料與關(guān)系鏈邏輯,、圖片語(yǔ)音視頻等富媒體收發(fā)邏輯、實(shí)時(shí)音視頻邏輯等),,QQ 通用組件(數(shù)據(jù)庫(kù),、協(xié)議編解碼、網(wǎng)絡(luò)傳輸?shù)龋?,以及線程/網(wǎng)絡(luò)/IO 等通用資源管理模塊和操作系統(tǒng)封裝部分,,由原來(lái)的各平臺(tái)原生語(yǔ)言實(shí)現(xiàn),統(tǒng)一下沉到 C++ 跨平臺(tái)層,。

為了控制項(xiàng)目質(zhì)量風(fēng)險(xiǎn),,NT 跨平臺(tái)內(nèi)核先接入用戶(hù)量相對(duì)較少,對(duì)功能補(bǔ)齊緊迫度高的桌面端,,完全用新架構(gòu)重寫(xiě)桌面端,。
在桌面端成功完成功能驗(yàn)證和質(zhì)量測(cè)試之后,我們開(kāi)始了向移動(dòng)端的遷移工作,,并順利完成了 iOS 和安卓平臺(tái)的集成,。

當(dāng)然,移動(dòng)端的接入遠(yuǎn)遠(yuǎn)不像圖中描述的這般容易,,接下來(lái)將介紹其中的解決方案和主要過(guò)程,。
3.3 IM 全鏈路重寫(xiě)升級(jí)
在新的 NT 架構(gòu)基礎(chǔ)上,對(duì) QQ 來(lái)說(shuō),,最核心的技術(shù)升級(jí),,是 IM 全鏈路的升級(jí)。IM 消息數(shù)據(jù)源復(fù)雜,,歷史包袱很重,,升級(jí)過(guò)程的遇到的第一個(gè)難點(diǎn)就是數(shù)據(jù)轉(zhuǎn)換及存量數(shù)據(jù)遷移到新版本問(wèn)題:
- 老版本的 QQ,好友消息沒(méi)有唯一標(biāo)識(shí)字段,,導(dǎo)入和去重影響大,。
- 2012年以前的版本,群消息沒(méi)有支持漫游,,消息無(wú)唯一字段,。
- 各平臺(tái)消息數(shù)據(jù)格式不同,,復(fù)雜度高,iOS 和 Android 分別有約200種消息類(lèi)型,。
- 富媒體(圖片,、視頻、語(yǔ)音,、文件)資源,,存儲(chǔ)的目錄結(jié)構(gòu)、命名都不同,。
- 特殊消息,,如結(jié)構(gòu)化消息、Ark 消息,、小灰條消息,,需要做轉(zhuǎn)換,完成業(yè)務(wù)的梳理和下架工作,。
- 還有因?yàn)楦鞣N功能的變遷帶來(lái)的遺留數(shù)據(jù)問(wèn)題,,如已經(jīng)退出或者解散的群和討論組等。
所以,,首先需要做 IM 的精簡(jiǎn),。項(xiàng)目團(tuán)隊(duì)基于用戶(hù)價(jià)值考慮,零基思維,,完成消息格式統(tǒng)一,,對(duì)消息和會(huì)話類(lèi)型進(jìn)行徹底精簡(jiǎn),為 QQ 消息長(zhǎng)治久安打下基礎(chǔ),。

有了全端格式統(tǒng)一和類(lèi)型精簡(jiǎn)的基礎(chǔ),,開(kāi)始用大小、性能,、安全性綜合最優(yōu)方案設(shè)計(jì)跨平臺(tái)統(tǒng)一的全新客戶(hù)端 DB,然后再考慮舊 DB 的數(shù)據(jù),,如何平穩(wěn)升級(jí)到新 DB,。移動(dòng)端和桌面端不同,活躍用戶(hù)全年在線,,有些手機(jī)本地純文本消息的 DB 文件超過(guò)10G,,加上富媒體、文件等,,總數(shù)據(jù)量超過(guò)100G,,而且移動(dòng)端又有存儲(chǔ)空間小、功耗敏感,、后臺(tái)殺進(jìn)程等多方面限制,,需要設(shè)計(jì)出一套周密的升級(jí)策略,,保護(hù)用戶(hù)核心數(shù)據(jù)資產(chǎn)不丟失。
方案核心要點(diǎn):
- 斷點(diǎn)續(xù)導(dǎo):移動(dòng)端場(chǎng)景,,進(jìn)程隨時(shí)可能被殺或退出,。確保消息不丟失、不重復(fù),。
- 用戶(hù)分級(jí):跟進(jìn)消息數(shù)據(jù)大小,,用戶(hù)分為三類(lèi),做不同的體驗(yàn)優(yōu)化,,減少對(duì)用戶(hù)的影響,。
- 優(yōu)化發(fā)燙和耗電:限制導(dǎo)入速度,防止手機(jī)發(fā)燙,。手機(jī)切后臺(tái)后停止導(dǎo)入,。對(duì)消息數(shù)據(jù)多的用戶(hù),引導(dǎo)用戶(hù)設(shè)置在后臺(tái)導(dǎo)入,。
- 監(jiān)控:做好各種導(dǎo)入異常上報(bào)監(jiān)控,,隨時(shí)跟進(jìn)用戶(hù)反饋。
通過(guò)設(shè)計(jì)周密的升級(jí)策略,,內(nèi)部多輪推演,,外部從百級(jí)開(kāi)始放量,全方位監(jiān)控,,并用兜底策略保障不丟消息,。最終結(jié)合監(jiān)控?cái)?shù)據(jù)和用戶(hù)反饋數(shù)據(jù),完成了全量用戶(hù)的全量數(shù)據(jù)平穩(wěn)遷移新 DB,。
3.4 核心功能優(yōu)化提升
不僅是消息,,在 NT 架構(gòu)重寫(xiě)升級(jí)過(guò)程中,對(duì) QQ 核心功能也一起做了更徹底的重構(gòu),,手機(jī) QQ 原生功能進(jìn)行了大規(guī)模解耦,,通用的部分進(jìn)行優(yōu)化并下沉為統(tǒng)一的 NT-Runtime 原生組件(NT 組件服務(wù)及框架層)?;谥貥?gòu)后的架構(gòu),,也對(duì)性能進(jìn)行全面優(yōu)化。
首先是消息相關(guān)核心模塊的優(yōu)化,。消息邏輯下沉到 C++ 跨平臺(tái),,也推動(dòng)上層進(jìn)行架構(gòu)刷新。以聊天窗口(AIO)為例,,基于全新數(shù)據(jù)流架構(gòu) + 數(shù)據(jù)預(yù)加載 + UI 邏輯并行化的設(shè)計(jì)思路,,完成單向數(shù)據(jù)流驅(qū)動(dòng)與異步加載渲染,系統(tǒng)資源全力供給 AIO 消息列表,,最終性能指標(biāo)提升明顯,,AIO 內(nèi)查看,、跳轉(zhuǎn)、滑動(dòng)消息,,順暢絲滑,。核心技術(shù)優(yōu)化方案:
- 采用基于單向數(shù)據(jù)流的 MVI 架構(gòu),實(shí)現(xiàn)業(yè)務(wù)解耦,。
- 預(yù)加載和異步渲染,,實(shí)現(xiàn)消息無(wú)縫滑動(dòng)。
- 消息加載并行化,,減少首屏和滑動(dòng)時(shí)的加載時(shí)間,。
- 消息動(dòng)態(tài)加載、釋放,,優(yōu)化內(nèi)存占用,。
- 200+業(yè)務(wù)組件懶加載,實(shí)現(xiàn)數(shù)據(jù)分層和按需加載,。
其它 QQ 主場(chǎng)景,,如消息列表頁(yè)、消息與富媒體收發(fā),、圖片視頻查看等,,也采用相同的路徑進(jìn)行優(yōu)化,最終性能全面提升,。

04,、總結(jié)
在手機(jī) QQ 超過(guò)20年的發(fā)展歷程中,應(yīng)用功能的不斷擴(kuò)展和代碼量的持續(xù)增長(zhǎng)積累了巨大的技術(shù)債務(wù),,給原有架構(gòu)帶來(lái)了沉重的負(fù)擔(dān),。通過(guò)一系列的架構(gòu)演變和技術(shù)升級(jí),手機(jī) QQ 成功地實(shí)現(xiàn)了從臃腫不堪到模塊化,、高效,、穩(wěn)定的轉(zhuǎn)變。
客戶(hù)端架構(gòu)由各端煙囪式架構(gòu)逐步升級(jí)為多端跨平臺(tái)復(fù)用的 NT 架構(gòu),,降低多端維護(hù)人力成本,,提升 QQ 全端開(kāi)發(fā)效率,為 QQ 的持續(xù)發(fā)展和技術(shù)迭代打下了堅(jiān)實(shí)的基礎(chǔ),。

展望未來(lái),QQ 將基于 NT 架構(gòu),,在技術(shù)創(chuàng)新的道路上繼續(xù)前行,,不斷進(jìn)行架構(gòu)優(yōu)化和技術(shù)升級(jí),為用戶(hù)提供更加流暢穩(wěn)定的產(chǎn)品體驗(yàn),。
-End-
原創(chuàng)作者 | 何金源
本文參與 騰訊云自媒體分享計(jì)劃,,分享自微信公眾號(hào),。