waxpatch實現上線app的熱更新

爲何須要 WaxPatch


不少狀況下,已經在 AppStore 上線的應用須要緊急缺陷修復,此時便須要使用某些技術手段,使應用程序可以動態下載補丁,進行缺陷修復。css


什麼是 WaxPatch

迄今爲止,腳本語言中運行速度最快的是 Lua。Lua 語言由巴西里約熱內盧天主教大學的 Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo 於 1993 年開發的。其最初的設計目的是提供一個方便嵌入到應用程序中得腳本語言。Lua 語言徹底使用 ANSI C 實現,其設計精巧,代碼優美。Lua 的解釋器總共在 200k 大小,並且運行速度大約是 C 語言的 1/5,語法比較簡單,即便不是專業的編程人員也容易掌握。html


2003 年,隨着暴雪的大型在線網絡遊戲 《魔獸世界》的發佈,Lua 逐漸被人們所知(《魔獸世界》的插件系統就是使用 Lua 開發), Lua 逐漸在遊戲界流行起來。如今國內幾乎大部分遊戲策劃都使用 Lua 語言來進行數值或者關卡的設計。編程


《魔獸世界》內的Lua編輯器


因爲 Lua 編程簡單,運行速度快,在 iOS 上, 一個支持使用 Lua 語言編寫 iOS 應用的項目 Wax 誕生了。Wax 項目容許用戶使用 Lua 語言調動蘋果 iOS SDK 的功能,進行應用程序的開發。安全


Wax Patch 項目是由 Wax 項目衍生而來,Wax patch 不只僅容許用戶使用 Lua 調用 iOS SDK 和應用程序內部的 API, 並且使用了 Objective-C runtime 的 class_replaceMethod 調用替換應用程序內部由 Objective-C 編寫的類方法,從而達到功能微調或者缺陷修復的目的。服務器


Wax/WaxPatch 主要特色:
網絡


● 全部 Objective-C 調用接口構建在 Objective-C runtime 之上,因此其調用 Objective-C 的 API 方式很是方便,不像調用 C/C++ 哪樣,必須先爲 Lua 編寫調用接口(有些技術能夠幫助 Lua 調用 C/C++ 編寫的動態庫而沒必要事先編寫調用接口, 可是在 iOS 上不能調用應用程序本身編寫的 API)。
app


● 對於 Objective-C 和 Lua 之間的數據類型轉換進行了封裝,使得開發者沒必要關心 Lua 和 Objective-C 的數據類型轉換,方便開發。編輯器

WaxPatch 工做原理

Objectvie-C 語言的特性和實現機制決定了任何其餘腳本語言對其進行調用都很方便。主要緣由在於 Objective-C runtime 提供了對於 類/對象 等 OC 類型的反射和自省機制。函數

相關的 API 以下:測試


typedefstruct objc_class *Class;

structobjc_object {

Class isa OBJC_ISA_AVAILABILITY;

};

typedefstruct objc_object *id;

typedefstruct objc_selector *SEL;

typedefid (*IMP)(id, SEL, ...);

SELsel_getUid(const char *str);

constchar *object_getClassName(id obj);

Classobjc_getClass(const char *name);

Methodclass_getInstanceMethod(Class cls, SEL name);

Methodclass_getClassMethod(Class cls, SEL name);

IMPclass_getMethodImplementation(Class cls, SEL name);

IMPclass_replaceMethod(Class cls, SEL name, IMP imp, const char *types);


藉由以上 API,則能夠經過字符串來動態調用 Objective-C 的類和對象的方法。


Wax/WaxPatch 調用 Objective-C 並非簡單得對 Objective-C runtime 的 API 進行 1 對 1 得封裝,而是把全部的 Objective-C 的對象\類\函數\等抽象成一個 WaxInstance,對 WaxInstance 進行操做。而 WaxPatch 則對 WaxInstance 的元表的 __newindex 屬性進行改寫,調用 class_replaceMethod 方法改寫父類的函數實現,使用 forwardInvocation 機制把針對父類的調用方法轉發到 Lua 改寫的類方法裏面。

動態補丁流程

咱們在一些項目中使用 WaxPatch 來實現熱更新機制,主要的流程以下所示。

1
補丁包發佈流程

2
客戶端請求補丁流程

3
客戶端使用補丁流程


整個流程遵循如下原則:


● 簡單有效,避免複雜邏輯。整個補丁包是全部補丁的全量包而不是增量包。


● 安全性要有保證。發佈版的補丁包是須要通過加密的,避免被惡意篡改。


● 正確性。在打補丁的過程當中,一旦出現錯誤,則馬上退出補丁流程,避免對原應用程序的流程產生致命的損壞。

4
全量補丁包格式

├── 20150701_01

│ ├──LoadPatchViewController.lua

│ └──init.lua

├── 20150703_01

│ ├──LTMoviePlayerViewController.lua

│ ├──LTPlayControlCenterView.lua

│ └──init.lua

├── LuaPatchManager.lua

└── letv_hotpatch_mapping.lua


① letvPatchManager.lua :補丁管理和執行文件,經過對客戶端版本號和 letv_hotpatch_mapping.ua 文件判斷補丁是否應該用於客戶端。

② letv_hotpatch_mapping.lua:補丁索引文件,記錄補丁適用於那個客戶端版本。

③ 20150701_01:補丁包分包,爲了方便補丁包管理,對單個補丁文件進行分組。

④ 20150701_01/init.lua:補丁分組執行文件。

⑤ 20150701_01/xxxx.lua:功能性的補丁。

整個方案主要由如下部分組成:


● 補丁包管理器:集成在客戶端內部,使用 Objective-C 編寫,負責從服務器下載補丁包,並解壓到客戶端的沙盒中。


● 補丁包:見上文。


● 補丁打包器:負責把全部明文補丁進行加密,並打包成 zip 格式供客戶端下載。

改進WaxPatch

block 調用和實現

WaxPatch 對於 Objective-C 的 block 支持不夠完備,雖然有一些 WaxPatch 的衍生版本增長了一些 block 的支持,可是並不能令咱們滿意,尤爲是 block 的參數支持上。對此。咱們本身增長了 WaxPatch 對 block 的支持,作到了對 block 的可變參數的支持。


安全性解決方案

因爲 WaxPatch 能夠作到對全部 Objective-C 的 API 修改(包括系統的和客戶端內部的)。因此理論上來講,一個非法的 lua 補丁能夠修改客戶端全部的流程和功能,以至於對最終用戶的信息形成傷害。


爲了保證客戶端功能和流程的安全性,在發佈的補丁包中,全部的 Lua 補丁源碼都由祕鑰進行加密。在客戶端方面,咱們針對 Lua 的解釋器進行修改,使用公鑰進行解密和驗證碼,避免非法的 Lua 補丁文件被執行。

其餘解決方案與結論

與 WaxPatch 方案相同的另一個方案是 JSPatch。JSPatch 使用系統內置的 Javascript 解釋器來動態 Javascript 代碼,達到與 WaxPatch 一樣的目的。其原理與 WaxPatch 基本相同。


通過調查,JSPatch 與 WaxPatch 相比,有一些固有的缺點沒法解決:


① 在 iOS6.0 系統上,Apple 並無開放 JavascriptCore 引擎,須要本身內置 JS 引擎,增長客戶端的體積。


② 因爲 JSPatch 使用系統的 JavascriptCore 引擎,咱們沒法去驗證 Javascript 補丁的合法性和有效性,對客戶端帶來了很大的安全隱患。


以上緣由決定使用 WaxPatch 的方案而不是 JSPatch 的方案。


軟件開發的正途應該是:以增強代碼質量和嚴格的測試來控制客戶端質量。雖然 WaxPatch 能夠作到對線上應用程序的缺陷進行快速修復,可是這種手段永遠只能做爲最後的一個防線,而不能過於依賴它。

 

轉自http://www.wtoutiao.com/p/w4d1Fz.html,謝謝原做者。 

相關文章
相關標籤/搜索