千萬級用戶的 Android 客戶端是如何養成的

1.0 時代:小、快、靈

2014 年 6 月份,in 發佈了第一個版本。到目前爲止,已經經歷了幾十個版本的迭代。在 1.0 時代,APP 的特色是小、快、靈。當時產品邏輯並不複雜,投入的資源不是特別多。由於處於探索期,因此產品的迭代很是快,爲了與之適應,in 採用了簡單的單工程的形式組織整個產品結構,高結構的層次也只有幾層,很是淺,如圖 1 所示。服務器

▲圖 1網絡

爲了兼容 H5 跳轉,in 參考了 H5 的一種路由協議做爲跳轉的支持。該時期,in 的用戶量增加迅速,1.0 末期已經達到了近 2500 萬。在這個框架下,in 一直衍生到 1.9 版本,這段時期使用輕量結構比較適合小步快走,即迭代很是快的形式,但這種形式存在一個明顯的缺點,即擴展性較差,個別類臃腫,不適合協同開發。隨着業務邏輯愈發複雜,參與人員不斷增長,如何提升協同開發效率成爲當務之急。架構

2.0 時代:繁、穩

in 在 2.0 時代有三個亟需解決的問題:框架

產品邏輯日趨複雜。複雜表如今兩方面:一是演進很是快;二是反覆。這是最致命的,由於開發過程當中 PD 可能會臨時作一些需求上的變動。所以,此時的框架必須適應產品的複雜化。 測試

代碼複用性差。1.0 時代,新模塊的開發主要基於原有的模塊,僅僅在原有的模塊上作一個很小的改動,代碼實現上卻須要進行大幅度的調整。spa

業務邏輯與基礎功能雜糅在一塊兒。由於業務上的一些變動經常會觸及底層的東西,致使穩定性不足。代理

▲圖 2日誌

基於這三點,in 在 2.0 時代進行了如圖 2 所示的重構。blog

首先,將全部業務分紅獨立的模塊,同時考慮產品邏輯中可能沒有想到的模塊。以 in 爲例,in 有圖片詳情頁,但從產品邏輯看,產品分爲我的中心、話題、品牌站等模塊,這些模塊都有各自的圖片詳情頁,圖片詳情頁並非一個獨立的業務線。初期,in 嚴格按照產品線去劃分業務邏輯模塊,因此開發出好幾套圖片詳情頁,這就是代碼複用性差。經驗教訓是,模塊不該徹底由 PD 決定,咱們必須很是熟悉產品結構,清楚有沒有共性的模塊能夠單獨抽離出來。接口

其次,業務模塊必須具備必定的配置性,便可擴展性。沿用剛纔的例子,咱們但願我的中心的圖片詳情頁具備顯示用戶打上去的標籤、貼紙等的功能,但品牌詳情頁可能並不須要這類功能,因此業務模塊必須達到可配置。分好業務模塊後,各個模塊之間相互獨立,但必然存在公共的功能,所以須要有一個底層的公共類庫作支持。公共類庫主要包括了一些基礎功能,好比網絡請求、圖片解析、本地日誌系統等。

最後,in 引入了許多第三方功能,而公共模塊是一個獨立工程。in 容許公共模塊直接使用第三方庫,但不容許其它模塊單獨使用。所以,第三方庫達到統一管理。同時,in 還沿用並強化了 1.0 時代的路由協議,推送能夠經過這套協議跳轉到推送頁面。

到此,in 基本解決了以前談到的三個問題,更重要的是提升了 QA 測試效率。

以往須要等全部功能開發完成才能交付給 QA,分模塊後,每個業務模塊均可以不依賴其餘模塊獨立運行。當一個模塊本身的業務開發完成後,均可直接交付給 QA。但與此同時,產品又產生了新的問題,即公共類庫臃腫,難維護,遷移成本高。

2.0 時代,in 的用戶量從 1.0 時代的近 2500 萬增加到 7000 萬。in 意識到每一次小的更新都會影響用戶的體驗,所以告別了原先快速迭代的發展模式,轉爲求穩。從開發的角度來講,是要提供更優質的服務。

後2.0時代:精、穩

▲圖 3

針對 2.0 時代產品公共類庫臃腫的問題,in 在框架上作了如圖 3 所示的改進。首先,上層沿用 2.0 時代的形式,但對公共模塊進行拆分,將公共業務抽成代理層,而且引入服務化的概念,將每個機組功能都抽成獨立的服務,好比網絡請求、圖片上傳,本地日誌等。這一版改進後,服務都被獨立抽出,相互之間是隔離的,每一個服務均可以交由不一樣的人去維護,內部高類聚。

與此同時,每一個服務都須要有容錯性,每一個模塊都須要有兜底方案,保證本身的輸出是穩定的,本身內部的問題不會影響其餘服務。

另外,底層服務不多被上層的業務代碼入侵,可儘可能經過協議或者是 API 的形式支持上層的業務邏輯,作到最輕量化級的接入。in 還對第三方庫作了封裝,將其經過代理的模式與本身的業務代碼隔離,這樣就能夠靈活地替換第三方類庫,而且大大下降維護成本。

服務化過程當中,in沿用了以前的通訊模塊,而且加入了一個統計框架。這個框架着重突出了服務化的概念,而且是本地服務化。它的優點在於很是的獨立,且具備很高的擴展性,每加入一個新的服務,都不會影響到其餘的服務,而且在整個架構的層面上來說,每個服務之間相互依賴的關係、調用的順序均可以很快地整理出來。同時,它還給in的產品矩陣打下了一個很好的基礎,將來若是推出一些新的APP,須要引用in老的代碼時,只須要選擇須要接入的那些服務,就能很快理出新的APP的架構圖,而且配置起來。

Extra: 巧、宜

▲圖 4

圖 4 爲 in 內統計框架,最大的特色是自動化、無侵入式。業界不少統計框架在路徑統計層面,主要是統計 Activity 層以及 Fragment 層,可是 in 的不少頁面是經過 View 等其餘形式實現的,所以沒法經過現有的一些統計框架進行頁面統計。對此,in 把全部的頁面都抽成 layer 的抽象概念,把全部的 layer 經過用戶的行爲路徑壓到一個 layer 棧內,最終以一個列表的形式發到服務器,而後在服務器創建一個數據倉庫,再經過 BI 部門整理數據倉庫得出每一個用戶的實際瀏覽路徑,包括每一個頁面的留存等。

模塊內的解耦

▲圖 5

耦合存在每一個模塊內。業界很常見的是用 MVC、MVP 等模式進行必定的解耦,in 主要用 MVP 模式。爲何 in 以前 Activity 經常寫得特別臃腫?由於它不只作了 Model 層的事,並且作了表現以及控制上的事。解決辦法是把 view 層單獨抽離,由 Fragment 去作 View 層的展示,而 Activity 層只專一於對數據的處理,實現 View 層跟 Model 層之間不直接交互,而是經過一個接口的形式進行溝通。

灰度發佈機制

灰度發佈機制主要是爲了支持產品的 A/B Test。in 的產品愈來愈複雜,用戶量愈來愈多,爲了實驗性的功能不影響全部的用戶體驗,只能容許一部分特定用戶看到新功能,而這須要經過代碼層作控制,即灰度發佈機制。如圖 5 所示,灰度發佈主要在業務層之上,它的配置所有由服務器端決定,確保每一個業務均可以作到灰度發佈。

模塊間通訊

模塊增長後,模塊間通訊成爲一個大問題,由於模塊之間是不可見的。兩個解決辦法:第一是經過一套反射機制達到每一個模塊間相對可見;第二是創建一套本身的基於觀察者、訂閱者模式的消息分發機制,in 的這套機制主要參考了 EventBus 以及谷歌最近開源的一個安卓響應式框架 Agera 相似於 RxAndroid ,這個框架能幫助模塊間通訊的現成模型的構建。另外,模塊間通訊有一個Sticky機制,問題就在於當頁面未打開以前,數據已經先到了,那麼該如何解決?就是經過 Sticky 機制,它能確保數據先到,頁面再打開的時候,數據能順利下發。

總結:

每一套框架都有本身的特色,可是萬變不離其宗,最主要的是要適合當前的項目規模和體量,更好的與業務結合在一塊兒,提升開發效率,下降維護成本。

相關文章
相關標籤/搜索