攜程移動端架構演進與優化之路
導讀: 目前攜程 75% 以上訂單來自移動端,App 幾乎承載了整個集團的所有業務形態。那麼無線服務端和客戶端底層架構如何支撐如此複雜靈活多樣多變的業務,並順利接入整個集團十幾個不同研發團隊開發的代碼,讓這麼多團隊協同開發,無縫集成在同一個 App 內,還能確保其質量和性能?這對移動端架構提出了非常嚴峻的挑戰。
從2013年開始,我們先後進行了不同路徑的多樣性架構探索,在實踐過程中也經歷了各種曲折與壓力,最終實現了2015年的這個全新架構,實現了無線服務端基於API Gateway的架構框架、客戶端的模塊化開發、測試與部署,支持運行期間的模塊實時載入、按需Lazyloding、Remote載入,從而實現模塊級動態升級以及代碼級熱修復,並且逐步推動數百人的客戶端研發團隊由不堪重負、效率低下的大版本大火車開發模式向模塊間獨立迭代、發布輕量級的開發方向演進。
同時在架構探索期間,攜程做了App相關的很多性能優化,比如底層網路通道治理的優化、應用層插件容器載入啟動速度以及存的優化、業務中間件Hybrid的優化等等,逐步保證隨著業務的不斷的迭代,能保證用戶的比較好的優化體驗。
一、App服務端架構變遷
1、早期App服務端架構
早期App服務端架構使用了傳統的PC無線開發架構,即在PC Web應用基礎上增加一些無線端的REST介面直接供給App訪問,沒有考慮架構的擴展性、 靈活性、安全型等因素。
圖1 攜程無線服務端架構V1
如圖1所示,服務端系統一方面以Web應用的方式提供給PC端瀏覽器訪問,另一方面為支持移動,在Web應用基礎上增加一些REST介面直接供App訪問。相應地,無線介面和Web應用作為同一工程開發,作為同一個應用部署,這種架構設計思路是很直接和自然的,可以快速把PC端功能複製到App上,其思想設計是在現有Web應用上打補丁,體現的是PC思維無線化,把App簡單作為PC端應用的翻版,並把兩者物理上捆綁在一起,在早期也能滿足當時的業務需求,但是隨著平台化的發展,以及業務越來越複雜和多樣性,這種架構設計帶來的一些列的問題逐步暴露出來,其中最突出的急需解決的有三個問題:耦合、重複造輪子、系統穩定性,具體如下所示:
強耦合
無線介面和Web應用緊耦合,Web端的修改會影響無線介面,Web端的發布導致無線介面被動連帶發布,Web端的Bug影響無線介面的可用性,反過來也一樣,無線介面的任何變化會影響Web應用。
此外其中酒店無線介面和機票的無線介面,或者其他BU無線的介面,也存在著較為嚴重的耦合問題,這種耦合帶來的問題,最嚴重最明顯的就是這個BU的介面調整或者修改Bug,有可能會影響其他BU介面的穩定型,從而帶來每次發布,要帶來更多的測試回歸工作。
重複造輪子
無線介面除了給App提供業務數據,還需要考慮一系列非功能性因素的介面功能驗證,如通訊協議和數據格式封裝、安全控制、日誌記錄,性能監控等,這些對每個無線介面都適用。如果App和後端系統直連,意味著每個後端系統都需要單獨支持這些通用功能,導致重複開發。一旦這些通用需求有變化(如對數據傳輸進行加密增強),所有後端系統都要強制同步修改和上線,給項目管理和產品發布帶來很大挑戰。
穩定性
App和多個後端系統直連,只要一個系統出問題,就會影響App的可用性,比如酒店服務出了問題比如變慢或者耗用CPU過多資源,其機票服務或者其他服務會受到一定影響,其典型的弊端就是缺乏故障隔離機制,缺少負載均衡、缺少監控、缺少熔斷等影響後端穩定性的問題,導致App的健壯性很差,非常脆弱。
2、攜程App服務端架構V2.0
基於架構V1.0三個比較嚴重的缺點,於是我們開始嘗試使用一種新的無線架構V2:基於API Gateway的無線服務端架構。
基於如圖2所示的無線API Gateway架構,具備如下功能特點。
對等隔離
App實際上和PC端瀏覽器是對等的,PC端應用有服務端,App也需要自己獨立的服務端,兩個服務端都需要針對自身的特點,獨立開發,獨立部署,同時實現邏輯和物理層面的解耦,從架構層面徹底擺脫PC思維無線化。
統一服務
核心邏輯從Web應用剝離出來,進行服務化改造,服務實現時不區分PC和無線,App和Web應用都依賴於這些服務,一套介面,多方調用。
統一無線API Gateway網關入口,保持系統的穩定性
提供統一的無線網關,所有App調用指向此網關,網關包括通用層、介面路由層、適配層。通用層包括通訊協議適配、數據封裝、安全、監控、日誌、隔離、熔斷、限流、反爬這些系統級功能,每個介面調用都需要同樣邏輯,這些功能統一由網關前置處理,避免重複開發。具體實現時,每個通用處理邏輯封裝成攔截器,遵循統一的過濾介面,並且做到可配置,網關依次調用這些攔截器,這樣可以支持通用邏輯的靈活擴展。
無線API Gateway應該目前很多公司都有自己的實現,目前市場上也提供了很多開源項目Zuul、Archaius、Hystrix、Eureka等幫助我們去實現自己的Gatway。
3、API Gateway具備的功能特點圖2 攜程無線服務端架構V2.0
攜程基於Netflix的開源項目Zuul開發了無線APIGateway架構如上圖2所示,其Gateway的職能是負責接收來自無線端的所有API請求,並將他們路由到正確的目標應用伺服器,並且提供限流、隔離、熔斷等功能,保證了無線服務的長期穩定運行,擁有的彈性容錯機制也減少了日常運維工作。同時該Gateway提供了多維度的監控數據,並與報警系統對接,實時監控線上情況,達到運維自動化。其API Gateway具有的幾個核心職能:路由、隔離、限流、熔斷、反爬、監控報警,具體如下所示:
介面路由:核心功能,需要根據各種條件將請求路由到正確的目的地。在實現上採用了路由服務,Gateway定期從路由服務獲取路由表,達到了解耦、實時更新的效果;經過通用邏輯預處理後,無線介面請求將進一步分發給後端處理(各個Adapter)。URL和Adapter在配置文件里做映射,分發邏輯根據請求中的URL信息,找到對應的Adapter,然後把請求交給Adapter處理。
隔離:由於Gateway接收了所有業務請求,請求多種多樣,當某類請求出問題時,不能影響其他請求處理。對此,Gateway實現了資源隔離,防止某類請求將資源耗光,繼而影響其他服務。
限流:對於任何一類請求,都設置了容量上限,並不能無限制處理。Gateway可以為每類請求設置並發上限,當到達上限時,Gateway將不在轉發請求,而是直接返回,保護後端服務。如果在後端服務過載的情況下,仍然轉發請求,只會惡化問題。
熔斷:當一個服務在不能提供服務時,Gateway如果斷續向它轉發請求,不但不能解決問題,往往還會惡化問題。Gateway引入了一個熔斷機制,當某一服務在過去一段時間內的錯誤比率到達一個閾值,Gateway則停止向該服務轉發請求,稱之為熔斷,特定時間過去後,Gateway會探測此服務是否恢復正常,正常則開始正常轉發,若不正常繼續熔斷。
反爬:Gateway積極對接安全介面,會根據IP、clientId、以及演算法校驗阻斷非法請求,保護後端服務。
監控報警:Gateway接入了Cat、Clog、並對接了運維報警工具。當出現問題時,會及時報警,儘早發現問題,減少損失。
4、API Gateway智能升降級
Gateway支持集中管控的同時,也帶來單點問題。假設後台某個服務介面,由於某種原因,性能有嚴重問題,對應Adapter處理很慢,那麼網關所在伺服器的線程很快被耗盡,導致單個介面拖垮整個系統。這種問題,單純通過增加機器,水平擴展網關數量是解決不了的,實踐中,我們引入了智能升降級機制來快速隔離單個介面的影響,從而實現了介面的自動隔離熔斷機制,其實現原理如圖3所示。
圖3 Gateway介面自動升級降級流程圖
針對特定一個介面,如果在一定時間間隔內(比如5分鐘),它的超時失敗率到了一定比例(比如5%),網關會對該介面做降級處理,隨機拋棄部分流量,比如只允許50%流量通過。下一個5分鐘再評估,如果失敗率還沒有改善,允許通過的流量降到25%,以此類推。如果成功率好轉,網關對該介面做升級處理,提升通過的流量比例,為了快速恢復,一般提升到原流量4倍,然後在下一個時間段再評估是否觸發升降級。
整個過程全自動智能處理(為防止誤判,可支持人工干預),這樣單個介面出問題,不會影響整個網關的處理能力。
5、攜程App服務端架構演進總結攜程App服務端架構通過一系列的拆分和整合,既優化了公司整體應用架構,又為App做大做強奠定良好基礎,其帶來的好處是全方面的,增加了架構的可擴展性、健壯性、穩定性、靈活性,並且提高了團隊的開發效率和團隊長遠的收益,其具體表現在:
實現PC端應用和移動端應用分離,使兩者徹底解耦,各自獨立發展,App從寄生藤變成並蒂蓮。攜程在做Gateway架構的第一步就是做PC端和無線端的業務解耦,以及各BU之間的業務解耦,實現各BU無線業務和PC業務的獨立部署、獨立發布。
底層核心的SOA服務基於統一業務規則提供邏輯和數據,介面不區分PC、無線或其他渠道(如Open API),避免重複開發,避免業務邏輯被污染。所有前端一視同仁,而且如果以後增加其他端,也不需要做過的改動,其擴展性和靈活性能滿足新業務拓展的需要。
根據無線本身的特點,支持系統層面的集中處理和業務層面的分散處理。通用邏輯支持插件化擴展,可以根據需要逐步補充;Adapter實現內外部介面的無縫轉換,可以針對無線場景,做邏輯增強(如服務聚合,客戶端性能埋點、介面性能監控)等。
移動研發團隊和各業務線研發團隊各司其職,每個團隊專註於自己擅長部分,移動團隊負責App客戶端和網關通用邏輯處理,PC服務端負責PC相關的業務邏輯處理,H5服務端負責H5相關的業務邏輯處理,各個研發團隊獨立研發和發布,不耦合,即各業務線研發團隊負責底層SOA服務及前端Adapter適配。
二、攜程App客戶端架構變遷
1、App早期架構
攜程App的第一個版本在2011發布,那時候App架構很簡單,基本上就是在傳統的MVC的架構基礎上封裝了一個數據服務層即代理數據層,如圖4所示。
圖4 攜程早期客戶端架構V1
在攜程業務發展的早期,移動App經歷從無到有的階段,為了快速上線搶佔市場,其移動App開發的MVC架構成了「短平快」思路的首選。
在如上圖4所示的MVC的體系架構中,業務控制層負責整個App中主要邏輯功能的實現;業務邏輯Model層則負責數據結構的描述以及數據持久化的功能;數據服務層作為數據的代理媒介層,主要負責與Control層進行數據通信,包括實現基礎框架數據通信,序列化和反序列的機制等;而移動界面UI View層作為展現層負責渲染整個App的UI。這種架構分工清晰,簡潔明了,並且這種系統架構在語言框架層就得到了Android和iOS的支持,所以非常適用於App的startup開發。
但是這種架構在開發的後期會由於其超高耦和性,從而造就龐大Controller層,而這也是一直被人所詬病。最終的MVC都從Model-View-Controller走向了Massive-View-Controller的終點,其最嚴重的結果就是Control層的代碼越來越多,在攜程內部很多類,早期都超過了2000行,同時Control層和View層之間存在一些較高的耦合。其對應的App工程結構架構如圖5所示:當時無論iOS和Android工程,都只有一個工程結構CtripWireless。
圖5 攜程前期App工程架構圖
單個工程去實現一個App的好處就是各個業務線的介面通信方便,調用簡單隨意,可以隨意使用工程中的任何公共和業務組件,並且接入學習成本低。但是隨著業務越來越複雜,以及各BU業務通信交互的需求越來越多,其各個BU的業務耦合越來越嚴重,這個直接為後期插件化Bundle架構埋下了伏筆。
基於攜程業務不斷快速發展,後來活躍用戶已經超過1億,日活用戶千萬,很快觸及到了當時Android虛擬機機制的設計缺陷,即移動端在Android上面臨了兩個比較嚴重的問題,這兩個問題導致的嚴重後果就是在2.3的系統裡面,用戶直接都不能安裝和使用。
一是單dex 65535方法數限制,二是線性內存分配器(LinearAlloc)限制。今天的Android開發者看到這兩個限制都不會陌生。前者是因為Android的早期設計中,對dex文件中方法id用16位整型標記,單個dex文件中的方法數無法超過65535,eclipse環境中生成不了未做過proguard的deBug apk。
後者則是dalvik虛擬機用來載入類的堆內存大小被硬編碼了,2.3以下是5M,2.3以上是8M,致使App無法安裝的原因就是因為這個堆內存被耗盡導致dexopt失敗。
現在來看肯定大家都覺得不是問題,因為Google已經給出了一些可靠的解決方案,輔以更加先進的gradle + Android Studio,開發者們可能根本不會再遇到這兩個經典問題,官方的MultiDex分dex機制解決了方法數限制的問題,其中main dex最小化原則,結合dalvik LinearAlloc heap size調整(修改到了16M),使得dexopt的失敗幾率大幅下降。而ART的出現徹底不再存在LinearAlloc這樣的限制。
但是我們回過來再看,那個在用戶Android 2.3還佔50%的時代里,是如何通過軟體架構調整解決這個問題的,其中的經驗有我們值得借鑒和學習的地方。
2、App V2.0架構基於上述我們遇到的問題,我們在原來的傳統架構上又做了重新調整和優化,提出了移動端架構V2.0,其主要設計思路就是:
在業務快速發展過程當中,發展到5.0的時候App上已經承載了很多業務功能,但其中一些功能用戶使用頻率比較低,並且之前快速試錯被證明效果不佳的一些功能也大量存留在現有版本中。這些不常使用的功能不應該始終佔用程序資源,所以從架構上進行縱向分離,保證主要重要場景的體驗,是這一時期的主要設計思路,這時期的架構設計圖如圖6所示。
圖6 攜程移動架構V2
要實現這個架構,第一步就是進行各個BU業務線的功能解耦,這個工作花費了整個團隊大概3個月時間3個App大版本的周期去進行。
進行功能解耦的重要思想,就是實行輕重分離,主次分明的思想;在代碼模塊的組織架構上進行重要的調整,保證主要重要的App功能快速迭代和性能穩定,將附屬的使用頻率不高的新功能,使用H5容器進行動態載入,所以在V2.0的架構上,攜程App就是個典型的Hybrid App ,可以看到剛開始就核心模塊酒店和機票採用Native 進行開發,其他模塊基本是採用H5去實現。
V2.0架構基礎上,做了一系列的工作就是將App中比較雞肋的功能比如客戶價值和轉化率低的功能轉成H5實現。這樣做的好處就是集中精力去優化Native業務體驗,同時也能減小Android因為方法數超標的限制壓力。
在V2.0這個階段還做了一件事情去解決dex 65535的問題,即將工程項目裡面出現的不再使用的類和不再使用的方法進行了集中清理,這樣的好處是代碼也整理乾淨了,如果方法數超出的不是太多的話通過清理就可以讓方法數減少到65536以下,同時還清理了不使用的jar包、重複引入的jar包以及對第三方jar包進行瘦身,一般來說jar裡面的方法數最好,清除一兩個無用的jar包就能大大的減少方法數。
同時這個階段還定義了一個原則,一些信息說明展示或者活動優惠頁面,非用戶主流程的頁面都是採用H5去實現,一方面減少開發成本,同時也是為了應對方法數增多的壓力。
上面三種方法都是從傳統的技術防守的角度即防止引入更多的方法和類,以及在原有工程角度上去瘦身,但是這兩個方法都不能本質上去解決單dex 65535方法數限制App不能安裝的問題,要想根本解決這個問題,就必須減少單個Dex的大小,使用新的技術進攻的手段去一勞永逸的去解決這個問題。
所以接下來做了比較重大的決定就是各個BU進行解耦,每個BU單獨獨立一個工程,每個獨立插件有獨立的UI界面邏輯和資源、存儲及網路通信數據處理邏輯,通過共用統一的基礎庫介面訪問網路服務、圖片庫、定位庫等。V2.0架構對應的App工程結構如圖7所示。
圖7 架構V2.0對應的工程結構圖
3、攜程Dex動態載入方案實現在當時為了徹底解決方法數溢出的問題,基於上面解耦的基礎上採用了多Dex分包方案,當時攜程的做法是借鑒Facebook提供的方案去動態分包,將一個apk中的dex文件分割成多個,然後動態載入dex文件。首先簡單描述下Facebook的思路:
Dex形式
攜程與Facebook的dex形式完全一致,這是因為我們也是使用Facebook開源工具buck編譯的。
Dex類分包的規則
Facebook將載入Dex的邏輯放於單獨的nodex進程,這是一個非常簡單、輕量級的進程。它沒有任何的ContentProvider,只有有限的幾個Activity、Service。
android:name="com.facebook.nodex.startup.splashscreen.NodexSplashActivity">
所以依賴集為Application、NodexSplashActivity的間接依賴集即可,而且這部分邏輯應該相對穩定,我們無須做動態掃描。這就實現了一個非常輕量級的依賴集方案。
載入Dex的方式
載入Dex邏輯也非常簡單,由於NodexSplashActivity的intent-f ilter指定為Main與LAUNCHER。首先拉起nodex進程,然後初始化NodexSplashActivityActivity,若此時Dex已經初始化過,即直接跳轉到主頁面。
Facebook載入Dex的方案,其載入流程圖如圖8所示。
圖8 Facebook 載入 Dex 流程圖
這種方式好處在於依賴集非常簡單,同時首次載入Dex時也不會卡死。但是它的缺點也很明顯,即每次啟動主進程時,都需先額外啟動一個nodex進程。儘管nodex進程邏輯非常簡單,但是也需要載入時間100ms以上。但是攜程對這個啟動時間非常敏感,當時推動產品很難會去採用這個方案。
基於這個方案的缺點,我們在其基礎上進行了優化方案,即能不能主進程直接載入Dex方案,具體定的方案策略如下。
Dex形式
Dex形式並不是重點,假定我們使用當前的Dex形式,即assets/secondary-program-dex-jars/secondary-N.dex.jar。
Dex類分包的規則
主Dex應該保證簡單,即類似Facebook,只需要少量與Dex載入相關的類即可,並且這部分代碼是相對穩定。我也無須去更改任何非載入相關的代碼。
載入Dex的方式
這個是重點,我們應該通過什麼載入方案去實現這樣的分包規則。首先大家明確若是點擊圖標,的確無須再起一個進程是可行的方案,但是問題就在於在Application初始化時,或是在attachBaseContext時,我們無法確保即將進入的是主界面Activity。可能系統要起的是某一個Service或Receiver或者Notification,這種跳轉方式是不行的。
圖9 Multiple Dex 載入流程圖
如圖9所示,有兩個關鍵問題需要解決:
通過何種方式掛起主進程?
掛起主進程過程中,是否會產生ANR?
關於問題1,進程同步可以使用pthread_mutex_xxx、 pthread_cond_xxx,但是mutex或cond要放於共享內存中,這種實現方式較為複雜,所以我最後實現時採用的是一個最簡單的方法即每隔95ms去檢測TempFile是否存在,如果存在則直接進入主程序,同時在載入dex的工作線程中去判斷,如果載入dex成功,則創建TempFile。
關於問題2,在掛起主進程的同時,去啟動一個工作線程去載入dex,也就是這個線程是非UI主線程,不會造成阻塞UI主線程的情況,經過多次測試,也確實沒發生ANR現象,這個通過分析ANR現象的本質就能得出這個結論。
基於Facebook的基礎上我們優化實現了動態載入Dex的方案,比較完美徹底地解決了因為方法數超標而無法安裝的問題,同時也不用擔心隨著業務發展,代碼中方法越來越多的問題。
同時在這個階段,也就是2015年初的時候,攜程開始全面由Eclipse工具遷移到Android studio + Gradle的構建方式,同時由於Google支持了MutilDex方案,所以後來就直接使用了官方提供的方案。
V2.0架構解耦之後,不同BU工程的依賴是解除了,良好的解決了以前各個不同BU相互依賴的問題,同時也可以支持多個團隊進行並行開發。但是這個階段的階段架構存在以下兩個明顯嚴重的問題:
源碼依賴
即會存在如果其他BU的工程修改了,如果沒及時通知對方人員,全全局報錯,整個工程編譯都無法通過,影響到其他BU的正常開發工作。
構建編譯速度慢
打包不可配置,構建編譯速度慢,因為攜程BU很多,業務也很全而複雜,大概解耦成有10幾個工程,因為不可選擇所以需全量編譯,所以造成一次構建速度最慢的時候差不多30分鐘,一般10分鐘以上,所以整個開發效率比較低,開發人員的體驗感也比較差。
4、App架構V3.0基於上述缺點,我們在V2.0的架構基礎上又進行了優化,提出了V3.0的架構,具體的架構圖如圖10所示。V3.0架構在V2.0的工程解耦升級的基礎上去完成了,V3.0架構是基於Bundle的動態載入插件化架構,即幾乎工程中的任何組織形態都可以看成Bundle, 而最終攜程App 由一系列的Bundle組合而成,運行在可以容納載入的Bundle容器DynamlicLoader中。
圖10 V3.0架構圖
如圖10所示,應用層的酒店、機票、火車票等都是一個個獨立的APK,它們之間獨立開發,互相不受影響。最終統一以插件的方式集成到統一的攜程APK裡面。酒店和機票之間通迅方式採取兩種方式,BUS數據匯流排跳轉 和 URL Scheme跳轉。
V3.0架構對應的工程結構圖如圖11所示。
圖11 架構 V3.0對應的工程結構圖
如圖11所示,現有的工程結構,有超過30個Bundle(apk),並且隨著未來業務的發展,其Bundle是越來越多。為了解決Bundle過多造成編譯速度過慢的問題,我們採用配置文件去動態靈活配置,各個BU需要使用什麼Bundle,通過簡單的一句配置,將其加到工程中即可,同時其他不需要打進來的Bundle支持aar(.a)和源碼依賴,按需添加依賴即可。
為了一勞永逸解決我們V2.0遇到的Dex方法數超標的問題,我們內部基於目前攜程App的現狀研發實現了一個動態載入的插件化框架DynamicLoader,支持即時載入,按需載入,遠程載入三種方式。即時載入,即剛開始就直接載入進來,按需載入是使用的時候才去載入,遠程載入即剛開始沒有這個工程,然後用戶通過遠程安裝就可以直接使用這個功能。這種機制同時也支持了我們後續使用到了Hotfix機制。在這裡首先簡單總結下目前市場上出現了比較著名的開源的插件化框架如表1所示。
表1 市場主流插件化技術對比
如表1所示,攜程在2015上半年開始著手研究自己的插件化框架,同時也對當時市場上的插件化技術做了調研,最終得出結果,當時市場上的主流框架都不能滿足攜程當時工程結構的現狀和當時插件化的需求,也就是接入其插件化之後,攜程的各個BU團隊需要很多額外的開發成本去實現整體遷移,同時還不能有效保證後續的插件化穩定性,基於此背景下,攜程的插件化應運而生,其實現原理是通過系統的ClassLoader動態載入類,通過系統的AssetManager去動態載入插件的資源,同時通過修改aapt的源碼去替換系統的Appt解決各BU資源之間衝突的問題。關鍵是各BU原有的代碼和現有的開發模式都不需要額外的去改動從而增加額外的開發成本,插件化的思想即一切皆Bundle組件的思想,每個Bundle有自己的版本號,通過BundleManager 去管理Bundle的升級。
在V3.0架構推進階段,為了需要支持按需載入的時候,其Bundle載入的速度,我們約定了一個規則:即每個Bundle載入的時間不需要超過500ms。所以需要對大Bundle進行拆分,比如酒店和機票內部又拆分了自己的6個Bundle。
V3.0架構就比較適合中到大型團隊,並且解耦之後,可以支持多個團隊的並行開發,也可以滿足多個版本的同時開發和發布。每個BU團隊所做的工作就是在發布之前提供一個Bundle即可,然後到發布集成階段,將其集成到攜程的統一APK裡面。
進入到2015年後,攜程在軟體架構上逐漸趨於平穩。在V2.0原有插件載入基礎上,研究了更多行業內Android應用的技術架構,並且也結合官方MultiDex的實現。
V3.0在V2.0解耦的基礎上,自己實現了動態載入插件化框架,並且在此基礎上增加動態熱補丁功能,通過攜程內部的Hotfix發布平台,實現了攜程客戶端補丁版本更新直接覆蓋,用戶無需安裝新版本就可以將嚴重的Bug修復掉。類似阿里的AndFix熱修復技術框架。
三、App架構V4.x
V3.0架構已經可以支持多個團隊的快速高效並行開發,但是技術永遠在前進,所以未來的V4.x架構我們還在進一步推進探索中,比如我們做Native App能否像Web網站一樣隨時部署,即用即取,能否做到跨平台的體驗良好的Native App開發,能否實現數十個工程秒級部署編譯,從而大大提高開發效率,這些問題是我們Native開發人員一直在探索追求的話題。
目前攜程正在推進和已經進行的技術架構:
推出了基於ReactNative的Moles框架;
基於FreelLine和LayoutCast的熱部署方案;
Bundle的更加輕量級組件化、服務化;
基於MVP和AOP的框架設計。
四、總結
架構是非常值得分享和討論的,好的技術架構能夠持續支持偉大的商業夢想。但是無論什麼優秀的可擴展性好的技術架構,都不能脫離於業務而存在,最終都會隨著業務的不斷發展,而同時其架構也在進行不同程度的演進與優化。一個好的架構首先是必須是能解決公司遇到的現實技術問題和符合滿足公司目前架構技術現狀,其次能帶來技術性的革新從而引領業務的發展。
其次做架構之前,要想清楚這樣設計的目的是什麼,通過架構設計使程序模塊化,做到模塊內部的高聚合和模塊之間的低耦合,做到基本符合迪米特、依賴倒置、里氏替換、介面隔離等原則。這樣做的好處是使得程序在開發的過程中,開發人員只需要專註於一點,提高程序開發的效率,並且更容易進行後續的測試以及定位問題。但設計不能違背目的,對於不同量級的工程,具體架構的實現方式必然是不同的,切忌犯為了設計而設計,為了架構而架構的毛病。
【作者簡介】南志文,攜程酒店研發部研發經理。曾負責App整體技術框架的架構研發與實踐,現負責酒店業務的迭代更新及App架構、性能優化。曾先後就職於阿里巴巴、巨人網路。本文首發於《程序員》雜誌。
推薦閱讀:
※攜程,請好自為之!
※李淼關於分析攜程財報的文章裡面有哪些錯誤?
※攜程和去哪兒合併後對機票市場B2C端的影響(2016/10/27更新)
※從零打造攜程無線持續交付平台 MCD 實踐