探索餓了麼移動APP的架構演進之路

探索餓了麼移動APP的架構演進之路

引言

時代演進,技術也隨之發展。到今天,APP已然成爲絕大多數互聯網企業用來獲取用戶的核心渠道。與此同時,伴隨着業務量的增加,越來越大、越來越多的APP也在不斷地、持續地挑戰着每個移動端研發人員的知識深度,而咱們的移動端技術人員也在這個不斷接受挑戰的過程當中,成就了今天的移動互聯網時代。餓了麼移動APP就是這樣一個挑戰,多用戶量、多業務量,在接受着更多更挑剔用戶的同時,默默地、不斷地演進着移動端的架構。sql

1 MVC

咱們常說,脫離業務談架構就是純粹的刷流氓。餓了麼移動APP的發展也是其業務發展的一面鏡子。編程

在餓了麼業務發展的早期,移動APP經歷從無到有的階段。爲了快速上線搶佔市場,傳統移動APP開發的MVC架構成了「短平快」思路的首選:服務器

探索餓了麼移動APP的架構演進之路

圖1 MVC架構網絡

這種架構以層次結構簡單清晰,代碼容易開發而被大多數人所接受。數據結構

在MVC的體系架構中,Controller層負責整個APP中主要邏輯功能的實現;Model層則負責數據結構的描述以及數據持久化的功能;而View層做爲展示層負責渲染整個APP的UI。分工清晰,簡潔明瞭;而且這種系統架構在語言框架層就獲得了Apple的支持,因此很是適用於APP的startup開發。架構

而後,這種架構在開發的後期會因爲其超高耦和性,從而造就龐大Controller層,而這也是一直被人所詬病。最終的MVC都從Model-View-Controller走向了Massive-View-Controller 的終點。併發

2 Module Decoupled

「短平快」的MVC架構幫助餓了麼移動APP快速搶佔了市場。而隨着代碼量的不斷增長,臃腫的Controller層也在漸露頭角;而業務上,餓了麼移動APP也從單一APP發展爲多APP齊頭並進的格局。這時候,若是下降耦合,複用已有模塊成了架構的第一要務。框架

架構中,模塊複用的第一要求即是代碼的功能組件化。組件化意味着擁有獨立功能的代碼從系統中進行抽象並剝離,再以「插件」的形式插回原有系統中。這樣剝離出來的功能組件,即可以供其餘APP進行使用,從而下降系統中模塊與模塊之間的耦和性;也同時提升了APP之間代碼的複用性。分佈式

餓了麼移動對於組件有兩種定義:公有組件和業務組件。公有組件指的是封裝得比較好的一些SDK,包括一些第三方組件和本身內部使用的組件。如iOS中最著名的網絡SDK AFNetworking,Android下OKHttp,都是這類組件的表明。而對於業務組件,則定義爲包含了一系列業務功能的總體,例如登陸業務組件,註冊業務組件,即爲此類組件的典型表明。高併發

對於公有組件,餓了麼移動採起了版本化的管理方式,而這在iOS和Android平臺上也早有比較成熟的解決方案。例如,對於iOS平臺,CocoaPods基本上成爲了代碼組件化管理的標配;在Android平臺上,Gradle也是很是成熟和穩健的方案。採用以上管理工具的另外一個緣由在於,對企業開發而言,代碼也是一種商業機密。基於保密性的目的,支持內網搭建私有服務器成爲了必需。以上的管理工具都可以很好地支持這些操做。

對於業務的組件化,咱們採起了業務模塊註冊機制的方式來達到解耦合的目的。每一個業務模塊對外提供相應的業務接口,同時在系統啓動的時候向Excalibur系統註冊本身模塊的Scheme(Excalibur是餓了麼移動用來保存Scheme與模塊之間映射的系統,同時能根據Scheme進行Class反射返回)。 當其餘業務模塊對該業務模塊有依賴時,從Excalibur系統中獲取相關實例,並調用相應接口來實現調用,從而實現了業務模塊之間的解耦目的。

而在業務組件,即業務模塊的內部,則能夠根據不一樣開發人員的偏好,來實現不一樣的代碼架構。如如今討論得比較火的MVVM, MVP等,均可以在模塊內部進行而不影響總體系統架構。

這時候的架構看起來更像是這樣:

探索餓了麼移動APP的架構演進之路

圖2 EMC架構

這種E(Excalibur)M(Modules)C(Common)架構以高內聚、低耦合爲主要的特色,以面向接口編程爲出發點,下降了模塊與模塊之間的聯繫。

該架構的另一大好處則在於解決了不一樣系統版本的兼容性問題。這裏舉iOS平臺下的WebView做爲例子來進行說明。Apple從iOS8系統開始提供了一套更好的Web支持框架——WebKit,但在iOS7系統下卻沒法兼容,從而致使Crash。使用此類架構,能夠在iOS7系統下仍然註冊使用傳統的WebView來渲染網頁,而在iOS8及其以上系統註冊WebKit來做爲渲染網頁的內核。即避免了Apple嚴格的審覈機制,又達到了動態加載的目的。

3 Hybrid

移動APP的開發有兩種不一樣的路線,Native APP和Web APP。這兩種路線的區別相似於PC時代開發應用程序時的C/S架構和 B/S架構。

以上咱們談到的都屬於典型的Native APP,即全部的程序都由本地組件渲染完成。這類APP優勢是顯而易見的,渲染速度快、用戶體驗好;缺點同時也十分突出:出現了錯誤必定要等待下一次用戶進行APP更新纔可以修復。

Web APP的優勢剛好就是Native APP的缺點所在,其頁面所有采用H5撰寫並存放在服務器端。每次進行頁面渲染時都從服務器請求最新的頁面。一旦頁面有錯誤服務器端進行更新便能馬上解決。不過其弊端也容易窺見:每次頁面都須要請求服務器,形成渲染時等待時間過長,從而致使的用戶體驗不夠完美,而且性能上較Native APP慢了1-2個數量級;與此同時還會致使更多的用戶流量消耗。另外一個缺點則在於,Web APP在移動端上調用本地的硬件設備存在必定的不便。不過這些弊端也都有相應的解決方案,如PhoneGap將網頁提早打包在本地以減小網絡的請求時間;同時也提供一系列的插件來訪問本地的硬件設備。然而,儘管如此,其渲染速度上仍是會稍微存在必定的差距。

Hybrid APP則是綜合了兩者優缺點的解決方案。餓了麼移動對於此二類APP的觀點在於,純粹展現性的模塊會更適合使用Web頁面來達到渲染的目的;而更多的數據操做性、動畫渲染性的模塊則更適合採用Native的方式。

基於以前的EMC架構,咱們將部分模塊從新進行了架構:

探索餓了麼移動APP的架構演進之路

圖3 Hybrid-EMC架構

Hybrid-EMC架構中,Web做爲一個子模塊,註冊加入到整個系統中,從而實現讓業務上須要快速迭代的模塊達到實時更新的效果。

4 React-Native & Hot Patch

通過這些年的業務發展,Hybrid提供的展現界面更新方案也逐漸地沒法知足APP更新迭代的須要。所以愈來愈多的動態部署的方案被提了出來,好比iOS下的JSPatch, waxPatch,Android下的Dexpose,AndFix, ClassLoader,都是比較成熟Hot Patch動態部署解決方案。這些方案的思路都是經過下載遠程服務器的代碼來動態更新本地的代碼行爲。

React-Native則屬於另外一種動態部署的方案,其核心原理在於經過JavaScript來調用本地組件進行界面的渲染。

而餓了麼移動APP發展到今天,各個APP綜合用戶量已通過億。所以一個很是小的Bug所帶來的問題均可能會直接影響到幾萬人的使用。爲了保證APP的穩定性和健壯性,Hot Patch方案也就成了當下最有待解決的問題。

根據80%的用戶訪問20%頁面這一80/20原則,保證這20%訪問最頻繁的頁面的穩定性就是保證了80%的APP的穩定性。所以,餓了麼移動對於部分訪問最頻繁的模塊進行了React-Native備份。當這部分頁面出現問題時,APP能夠經過服務器的配置,自動切換成React-Native的備份頁面;而與此同時開發人員開發一個小而精的Hot Patch來修復出現的問題。當Hot Patch完成修補後,再切換回Native APP的原生功能。

這時候的架構看起來會像是這樣:

探索餓了麼移動APP的架構演進之路

圖4 HotPatch-EMC架構

HotPatch-EMC的架構主要目標在於解決移動APP的穩定性問題。經過RN與Native的主備,能夠減小系統APP出錯帶來的失誤成本。

5 結語

咱們都知道,對於軟件工程來講,這世上沒有銀彈。對於架構而言其實也很是的適用。業務的不斷更新,帶來了餓了麼移動APP架構的不斷演進。

架構沒有真正的好壞之分,只要適用於本身的業務,就是好的架構!

歡迎工做一到五年的Java工程師朋友們加入Java架構開發:878249276

羣內提供免費的Java架構學習資料(裏面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用本身每一分每一秒的時間來學習提高本身,不要再用"沒有時間「來掩飾本身思想上的懶惰!趁年輕,使勁拼,給將來的本身一個交代!

相關文章
相關標籤/搜索