天天看點

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>摘要:</b>在2017雲栖大會深圳峰會開源專場上,阿裡巴巴手淘技術部資深技術專家倪生華(玄黎)做了題為《atlas-容器化演進之路》的精彩演講,玄黎從atlas的發展、特性、技術原理以及開源運作等四個方面為大家分享了手淘的移動容器化架構atlas的技術演進之路。面對all in手淘的航母戰略,如何實作元件化?本文不容錯過。

以下内容根據嘉賓演講視訊以及ppt整理而成。

本次分享将主要分為以下四個部分:

atlas的發展

atlas的特性

atlas的技術原理

atlas的開源運作

<b>一、atlas的發展</b>

<b>atlas開發動力</b>

當大家打開手機淘寶時,可能就會發現阿裡巴巴的手淘的業務其實很大,基本上可以在手淘中看到阿裡巴巴所有的業務,比如聚劃算、天貓等等。特别是在2013年的時候,整個阿裡集團開始all in手淘,手淘成為了阿裡巴巴集團的一艘航母,基本上所有的業務都需要能夠在手淘上運作。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>atlas發展曆程</b>

但是突然發現手淘自己還沒有準備好,那時候手淘基本上一個月釋出一個新的版本屬于比較正常的情況,但是當突然多出了100多個業務,而這些業務可能幾天就需要更新一個版本,這樣就出現了平台的發展速度趕不上業務發展速度的情況。除此之外,另一個變化是之前隻有一個團隊進行開發,但是all in手淘戰略提出之後,手機淘寶包含了100多個業務,團隊之間的協作成為了非常大的問題。是以在這樣的需求變得越來越強烈的情況下,手淘非常需要一套架構來支援整個阿裡事業部幾百個團隊的協作以及各自業務的快速疊代。是以從2012年開始,手淘技術團隊就開始嘗試建構移動容器化架構,那個時候的atlas架構還是基于插件化的設計,程序之間互相隔離,插件彼此獨立,架構完全是一個提供服務的空殼。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>插件化架構</b>

插件化的架構政策使用了兩年,後來就發現這樣的政策存在着很多的問題,是以在2014年,手淘技術團隊痛定思痛,完完全全地重寫了一遍atlas,是以現在大家所看到的開源的atlas其實就是第二版的atlas,也就是從原來多程序的方式轉化到單一程序的方式,但是同時也實作了多程序的周遊系統,支援業務的獨立開發、獨立部署、獨立運作。到2015年的時候,基于業務的需求重新做了按需加載,實作了對于遠端元件的支援,并且對于容器進行了更新。是以從2015年到2016年,atlas在阿裡巴巴内部穩定運作了兩年,而在207年初的時候之前正式開源了atlas這個項目。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>插件化所帶來的問題</b>

接下來首先介紹一下atlas在2012年時的插件化架構設計。如下圖所示的就是當時atlas插件化的架構,最底層是容器程序:containeractivity與containerservice,在這之上會存在各種各樣獨立的插件程序,比方說天貓、聚劃算等等。這些插件程序分别都有各自的生命周期,獨立地進行管理。為了實作這樣的架構就需要在系統層實作很多的事情,也就是基本上系統所要做的程序管理,atlas 也都要完成。當時插件化的架構設計所帶來的好處就是插件之間的隔離,包括記憶體排程等都進行了完全的隔離;除此之外就是不需要再次開發,有新的業務進來可以部署并且直接運作。這樣的架構設計大概運作了兩年,其實也才真正完成了一年多時間就發現了一些非常嚴重的問題。第一個問題就是因為形成了整個實體的隔離,所有的apk都是隔離的,但是手機卻不是隔離的,使用者會将這些apk都放在同一個包裡面。一個簡單的例子就是天貓引進了一個庫,聚劃算也引進了這個庫,在兩個apk包裡面,并且可能有很多代碼屬于這個庫的,而這種情況可能出現的比較多,是以代碼的可用性就會非常非常差,這樣就會對于後面的統一排程以及管控上面造成非常不利的情況。第二方面,因為atlas 插件化的架構設計是基于程序式的,大家都知道程序與線程相比更加重量級,是以使用插件式的方案要比原生的不采用插件式的方案的記憶體消耗要更大。第三部分是因為要在系統之上隔一層,是以整體的插件适配情況會比較差,插件每釋出一個版本甚至每個廠家釋出一個版本都需要去重新進行識别。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>元件化的思考</b>

這樣的插件化架構運作了兩年的時間,後來團隊發現簡直痛不欲生,是以在2014年初的時候整個團隊就開始重新思考手淘到底需要什麼樣的架構。基于之前整個插件化的方案,在經過了深入的思考後認為:

首先,手淘需要高複用性,手淘不是一個大雜燴,需要進行統一地管控,對于所有的中間件、所有的服務都需要有一方進行統一管控。

第二方面就是要做到低侵入性,對于開發者而言,他們不需要感覺容器的需求,隻需要進行編碼就可以了,這就是低侵入性,也就是開發者不需要對于系統由特别深刻的了解就可以運用大量的黑科技,比如說開發者并不需要了解安卓系統底層設計,而隻需要在安卓容器上使用java層的api就可以完成自己想要實作的功能。

第三個方面就是高可用性,高可用性也好,性能也好,要保證使用了插件不能對于應用的性能産生太大的損耗。

最後一個方面也是業務插件方提出的請求,就是希望業務和業務之間使用插件隔離開來,獨立地進行開發和調試。業務今天可以跟着手淘的航空母艦一起跑,未來也可以自己獨立地運作。

在2014年初的時候,手淘技術團隊在想清楚這四條原則之後,大概花費了一個月的時間建構出了新版的atlas架構體系。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>atlas體系</b>

如下圖所示就是現在的atlas體系結構,在整個容器中沒有進行混淆之前不會超過100個類。像圖中最下面的一層,稱之為hack層,包括os hack toolkit &amp; verifier,這裡其實主要是為了對系統能力做一些擴充,然後做一些安全校驗。上面的一層是bundle franework,就是我們的容器基礎架構,這一層仿照整個osg2層容器的概念定義了一層所有容器插件化的生命周期提供bundle管理、加載、生命周期、安全等一些最基本的能力。再之上的一層是運作期管理層,主要在容器的運作時,對于所有bundle的版本控制進行管理;以及清單,會把所有的bundle和它們的能力列在一個清單上,在調用時友善查找,這樣就可以知道到底有多少個容器;這一層還存在對于類加載器以及資源的代理,這裡就是和業界一些插件化架構機制類似的地方,atlas會代理系統的運作環境,讓bundle運作在自己的容器架構上。這一層最右邊的則是整個運作期間的監控器,可以監控運作的情況,也友善了工程期開發調試。最上面一層就是業務,這一層是面向開發者的,開發者隻需要知道存在atlasbridgeapplication就可完全去使用容器的能力,除此之外還有tools,可以用來進行校驗和判斷。這樣帶來情況是使得元件開發與在背景的開發是一模一樣的,經過一個代理的resource和classloader進行操作。而這些東西對于元件開發而言,完全不需要深入了解,這部分内容會在之後的章節會繼續展開進行分享。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>atlas業務分層</b>

atlas的整體業務分層如下圖所示。底層稱之為服務層或者是宿主app,大家都知道很多應用會引入第三方的中間件或者元件,将這些元件放在基礎服務層,也就是上層的業務統一會使用的業務能力層,而這一層的業務能力不會直接去調用應用子產品。在服務層之上就是各自的業務子產品,這些業務子產品可以和技術服務層進行互動,也可以和其他業務子產品通過協定的模式進行互動。但是如果業務子產品需要使用到一些公共的業務子產品,就可以抽離出一層偏業務的服務。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

基于整個atlas的容器,手淘做到了什麼樣的程度呢?大概是從2013年開始,手淘開始開發atlas容器架構,到2014年正式成立。下圖中左邊的這張圖就顯示了手淘android端的釋出次數,從2013年釋出了42次增長到2016年釋出了600多次,這裡的版本是指的真實傳遞到使用者用戶端上面的。右面這張圖是從手淘團隊從2013年開始到2016年為止,釋出一個新版本所需要的時間情況,大家可以看到在2013年釋出一個新的版本需要平均10天以上的時間才能傳遞給使用者,而到了2016年幾乎一兩天就可以傳遞給使用者一個新的版本,可以認為手淘的業務每天都在發生着更新。在這樣的快速疊代之上,目前整個手淘大概會有70多個備案明确的業務;對于人員而言,手機淘寶自己的部門大概會有400多個工程師,而整個阿裡系裡面還有20多個bu在參與其中。這些在android方面的基礎都是基于atlas來做的,基于atlas才能實作對于綜合業務的快速支援。

<b>atlas帶來的價值</b>

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>二、atlas的特性</b>

在第一個章節介紹了atlas的整體發展曆程,atlas的發展其實是基于整個業務的快速疊代和分工協作進行的,接下來為大家分享atlas的一些特性。從2015年開始atlas進行了元件化,整體進行了更新,擁有了很多新的特性。

對于atlas的特性而言,可以大緻如下圖所示。首先,atlas對于開發者而言是無侵入性的,沒有任何沖突,在開發過程中不需要做任何感覺,開發者原來是怎樣開發的現在依然是怎樣開發。第二個特性就是元件是獨立進行開發和調試的,元件的開發可以不依賴于其他子產品。第三個特性就是高相容性和高穩定性,atlas從開始運作到今年位置在阿裡實際運作了4年多,元件化設計從2015年開始到現在已經運作了2年多,扛過了兩年的雙11。同時它具備動态更新能力,所謂動态更新能力就是目前atlas可以支援元件獨立開發,atlas相容從android 4.x一直到android 8,而且對于市面上所知道的rom都是相容的,而且目前沒有發現任何一個rom在手機上面會出現問題。目前手淘已經穩定運作了2年多,整體手淘的crash率一直維持在萬分之五左右,因為容器導緻的crash占比小于百分之一,而手淘atlas的性能損耗在5%之内,也就是使用容器和不使用容器加載方式來點選的性能損耗在5%以内。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

對于atlas的特性而言,在另一個角度上将其分為兩部分。第一方面atlas可以做到工程師獨立,在所有的開發過程中都可以做到獨立開發、獨立調試、獨立內建以及獨立釋出,也就是說業務開發可以完全脫離手淘,可以認為沒有這個大的ip存在,就像一個web應用一樣将其放上去,甚至不用去找應用市場進行資訊釋出。這就是在整個工程化體系上面每個bundle獨立開發以及獨立釋出。第二個方面是在整個運作期間,之前提到了本質上是基于os g2去做的,因為atlas實作了資源的隔離和aapt分段,運作期中在bundle和bundle之間也實作了資源的隔離。是以總體而言,atlas可以實作透明,靈活,穩定,靈活,這同樣也是在最開始建構atlas時所提出的四個要求。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>atlas與其他元件化方案的對比</b>

在下圖中将市面上所有元件化解決方案進行了羅列。對于元件化方案可以進行對比去看,不一定有好壞之分,隻是适不适合某個特定的場景,比如對于需要對元件進行獨立支援和獨立加載的apk适合什麼樣的元件化方案,atlas就不支援這樣加載獨立的apk,如果需要支援加載web apk或者第三方的apk可能選擇atlas并不合适。第二點,atlas支援動态更新所謂的插件宿主,也就是宿主容器中間件這個層面也是支援動态更新的。第三點就是對于四大元件的動态啟動,現在對于四大元件的動态增加atlas是部分支援的。對于首次插件啟動的性能而言,如果插件引用了容器化或者元件化的方案,那麼在插件首次啟動時,性能都會有一定的影響,這是因為引入這樣的方案會将資源和類的加載過程向後推。在atlas中對于插件首次啟動的性能進行了優化,是以使用者可以感覺到插件啟動是非常快速的,這個優化是基于系統層面的,并且是基于一個程序的,是以實體隔離是沒有做的,如果相關元件挂掉了,那麼這個插件也會挂掉。而且atlas的hook的程度其實是非常輕的。對于代碼運作隔離而言,其實因為atlas的整體運作機制基本上可以做到元件群組件之間的隔離,目前非侵入式這些atlas都是可以做到的。對于插件的懶加載,atlas采用的政策是隻有在用到插件時才會進行加載,一個像手淘這樣的應用可能會有70多個子產品,但是使用者可能并不會全部使用到,是以沒有必要在一開始全部加載進來,隻需要在使用者要使用的時候把子產品加載進來就可以,比如使用者在手淘中點選了天貓或者聚劃算,才會将這些插件啟動起來,不使用時不會啟動。其實下圖中标紅的部分也就是與其他的元件化方案相比,atlas的一些特點,如果這些特點正好符合應用的需求,就可以嘗試使用atlas,如果這些特點與需求相差甚遠,可能atlas就并不适合這樣的場景。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>atlas動态能力</b>

以上是在元件化的方案上進行對比,而現在比較火的就是動态更新能力。其實在阿裡運作的最多的還是基于atlas這一套的東西,接下來就為大家分享一下atlas的動态能力。這部分從六個方面來看:

支援類型,目前atlas支援class檔案,so和資源檔案的增删改操作,可以說是全類型的動态能力。

相容性,atlas适配android 4.x - 7.x版本,而且已經線上上穩定運作了2年多的時間。

高性能,通過去verify等手段,達到極小的性能損耗。

更新檔大小,atlas自己有一套cache代碼的git,包括os、資源檔案的利用,通過精細化diff的方法,達到非常小的patch包,手淘在增加業務時包的大小也不會也太大增加。

成功率,目前成功率還是非常高的,與業界相比,具有較高的部署成功率和效率,目前影響成功的最大因素就是使用者的磁盤空間。

開發透明,這一點也就是對于開發者友好。如果開發者需要去開發動态部署的能力或者動态更新的能力,其實不需要去關心應用是不是動态更新的,隻需要在業務代碼裡送出一個新的版本,atlas會幫助開發者自動生成diff包。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

目前存在的局限也可能是所有動态更新中都會存在的局限,就是暫時不支援manifest中的權限等内容,如果涉及到manifest裡面的權限就需要做系統的注冊,是以這些atlas還是不支援的;而且atlas對于activity,service的新增也是有限支援的。

<b>三、atlas的技術原理</b>

上面就主要為大家介紹了atlas的兩個特性:元件化和周邊化。接下來會為大家簡單地介紹一些atlas的整個技術原理。

<b>類加載機制</b>

元件化也好,動态部署也好,都需要進行類加載來完成這樣的事情。大家都知道所有的類加載都是基于classloader來執行的,atlas的核心就是在每個bundle下面去設定一層bundleclassloader,bundle類加載器的邏輯則是在bundle進行查找的時候首先會去查找自己的bundle裡面有沒有這個類,如果有的話就不會再去尋找,如果沒有就會去找host,也就是整個宿主類的classloader裡面有沒有這個類,如果還沒有就會去系統或者其所依賴的關系中去找尋這個類。對于下面整張圖而言,其實原理非常簡單,還是classloader雙親委托這樣的一件事情,atlas隻是在android和java的基礎之上設計了兩層的classloader,通過自己定義的classloader的加載規則來實作對于整個宿主的隔離,從這個意義上講是比較簡單的。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>資源處理機制</b>

除了類之外,開發過程中比較關心的就是資源問題。那麼atlas的資源處理機制時怎樣做的呢?其實也非常簡單,但是還是會與classloader有所差別的。在android某些系統上面将資源進行隔離時會存在一定的相容性問題,是以atlas采用了如下圖中右圖所示的另外一種做法,把所有的bundle資源在編譯期進行了隔離,每個bundle的資源段都會通過ap去進行修改,給出一個統一的資源字段,通過在加載的時候将每個bundle的資源放到assetsmanager裡面。atlas沒有做運作時的隔離,而是通過編譯期的資源分段模式實作了資源隔離的方案,是以在bundle裡面可以使用到bundle自身的資源也可以使用到宿主的資源。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>動态更新能力</b>

目前atlas動态更新支援三種模式:

第一種模式指的是元件遠端下載下傳。當拿到這個需求的時候,大家可能都會比較慌,有一個bundle特别大可能無法裝入到apk裡面,而在atlas裡面其實做的事情也很簡單,它隻是編譯的過程中讓這個bundle參與編譯,但是在最後釋出過程中将這個bundle去除掉,在需要它運作的時候從遠端把這個bundle下載下傳下來。這種方式使用的比較多的地方就是手淘的預裝包,一般現在的apk都會非常大,通過這種方式可以将主要功能放入到update apk裡面去,一些次要的功能可以通過遠端包配置,當這個bundle啟動的時候再去下載下傳遠端包,這就可以認為是從無到有。當然這并不是嚴格意義上的從無到有,因為在編譯的過程中已經将所有的manifest都已經打包進去了,次要的功能通過遠端下載下傳的方式進行配置。

第二種動态加載的模式是業務元件動态更新。因為整個宿主類或者中間層的服務類本身的變動一般而言都是比較少的,基本上這些類不會每天都發生更新變化,應對這樣的需求可以采用業務元件動态更新,因為可以認為是完全獨立的classloader程序,可以認為是剝離在整個android系統的程序之外的,可以實作什麼時候需要就去加載什麼樣的資源。業務元件的動态更新其實是通過元件diff和merge的過程進行更新的,并且這樣使直接在元件的生命周期内做,相容性極好。因為不會涉及到系統操作,隻是一個資源虛化,原來是直接加載資源,現在是patch下來之後直接生成一個新的資源,這種方式的相容性會非常好。

第三縱動态加載模式是如果真的需要修改宿主類時就回歸到常見的通過類、資源、so檔案等的diff算法,通過merge算法來實作更新,有比較好的相容性。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>bundle的部署</b>

下圖是現在bundle部署的diff過程。在進行bundle打包的時候可能會打一份源代碼,釋出哪個就會在倉庫裡面存儲一個版本,第二次釋出的打了一個新的包,并對每個資源進行diff,比如class與class之間通過dex格式形成一個新的classes.dex。resource與resource之間可能會去基于md5進行diff。而對于research和assert會基于dex merge的模式進行diff。對于資源檔案也是一樣,基于手機上的檔案和patch檔案生成一個新的資源合集,基于所有的patch會生成新的營運期的apk檔案的容器模型。今天可能釋出一個patch明天還會釋出一個patch,為了支援patch最小化就需要使用增量釋出。增量釋出能夠使得使用者隻要更新了一次,下次再進行更新隻要發生變化的資源和類就可以了,不需要将所有的從源檔案到類都更新,這樣就可以保證更新量比較小,速度也比較快。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>目錄結構</b>

下圖是atlas在手機上面的目錄結構。其實在每個bundle下都會各自有一個目錄結構,第一次釋出完成之後會合成一個version 1,在後面patch目錄中會合成一個patch 1,當釋出了第二個版本時,會在運作的時候去取version 2這個版本。由于基于目錄結構來做的,是以復原操作也會非常簡單。是以如果基于動态部署來實作,更新版本後如果發現有問題,隻需要在服務端下發一個指令就可以删掉或者復原,而不需要使用者進行操作。在服務端也存在清單的概念,是以可以精确感覺到哪幾個版本或者子產品是存在問題的。是以基于這套機制,用戶端的釋出和之前服務端的釋出是一模一樣的,開發者可以去随時釋出或者随時復原,大大地提升了釋出和復原的效率,一個指令下去可能幾秒鐘之内就能夠復原到上一版本或者之前的版本上去。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>中間件代碼部署</b>

下圖展示的是atlas為了規避性能損失的一個措施,其實在整個容器這部分,因為android的限制需要根據classloader來更新,會使用插裝的方式和verify機制。而現在發現基于系統的dex機制可以不使用插裝的機制,是以現在atlas的做法是使用者手機上面設定多個dex,如果新的dex和原來是重複的,就會将重複的dex删除掉,自動合并到新的dex裡面去,這樣做的好處是這個機制完全符合谷歌的manifest規則體系的,其次因為取消了verify機制,整體的性能會非常快。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>宿主資源部署</b>

因為安卓本身有一個限制,所有的資源必須得在base包裡,新增一個資源是不生效的。是以一個做法是在打包的時候預留很多空資源。另外更新已有的資源則通過資源覆寫來完成。在宿主中會預留一些空資源段,當新增的時候就可以适應這些主dex預留的資源段。也就是如下圖中顯示的會有很長一段null的資源,如果增加了資源就需要對于這些标記為null的資源段進行更新。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

<b>四、atlas的開源運作</b>

到目前為止,手淘技術團隊有一個專職的開發團隊去維護atlas。目前整個阿裡系能夠看得到的使用了atlas的應用有很多,而且目前阿裡巴巴對内和對外的atlas是一套代碼,是以大家不必擔心atlas開源之後不會進行維護了。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

下圖展示的就是atlas未來的一些版本計劃。接下來首先還需要繼續提升atlas的自身穩定性以及相容性。其次,因為開源了atlas,是以也需要降低接入的成本。大概6月份,希望能夠提供出ide快速調試開發插件,來完善atlas工具鍊。并希望新增支援動态service/适配android o。大概在9月份atlas會提供極簡接入工具,并對于動态部署擴充(小patch方式)/dexmerge的算法進行改進。

阿裡巴巴開源移動容器化架構Atlas的技術演進之路

繼續閱讀