構建高可伸縮性的WEB交互式系統(上)
可伸縮性是一種對軟件系統處理能力的設計指標,高可伸縮性代表一種彈性,在系統擴展過程中,能夠保證旺盛的生命力,通過很少的改動,就能實現整個系統處理能力的增長。
在系統設計的時候,充分地考慮系統的可伸縮性,一方面能夠極大地減少日后的維護開銷,并幫助決策者對于投資所能獲得的回報進行更加精準的估計;另一方面,高可伸縮性的系統往往會具有更好的容災能力,從而提供更好的用戶體驗。
WEB交互式系統的可伸縮性主要體現在兩個方面:
- 平臺的可伸縮性:隨著WEB技術的發展,越來越多的平臺開始使用WEB技術來構建系統,一方面不同的平臺提供的環境支持存在著各種差異;另一方面隨著平臺的發展,不斷的會有一些舊平臺退出歷史舞臺,新平臺轉而成為主流平臺;因此構建的WEB系統需要能夠快速的響應此類變化就需要其具備良好的平臺伸縮性
- 模塊的可伸縮性:隨著系統功能不斷增刪更新需求的變化,系統可能會變得越來越復雜,冗余信息也可能會越來越多,改動所帶來的影響范圍也可能會越來越大,因此良好的模塊伸縮性可保證系統具有良好的可維護性,讓系統始終處于最佳狀態
WEB交互式系統的主要應用包括:
- 桌面端/移動端網站類系統(如 網易云課堂、易信WebIM、Lofter移動WEB版等)
- 移動混合應用(如 網易云相冊IPad版、Lofter等)
- 桌面混合應用(如 網易云音樂PC版、網易郵箱助手等)
本系列文章主要分為兩個主要部分對可伸縮性進行闡述,分別是平臺的可伸縮性和模塊的可伸縮性。本文是系列文章的第一篇,討論平臺的可伸縮性。
平臺的可伸縮性
WEB交互式系統對平臺的可伸縮性主要表現為:
- 可擴展性:對于新興平臺能夠快速進行支持
- 可縮減性:對于過時的平臺冗余信息能夠以最小的修改方式剔除
我們先介紹一下WEB交互式系統的目標平臺的情況。
平臺分類
根據系統所在容器的差異,我們將平臺分為瀏覽器平臺和混合應用平臺兩大類。各分類的詳細說明見下文所述。
瀏覽器平臺
按引擎劃分
瀏覽器平臺,按照主流引擎可以劃分為以下幾類:
混合應用平臺
根據混合應用的宿主平臺的差異,我們將混合應用的目標平臺分為以下幾類:
宿主 |
說明 |
Android | Android系統的混合應用,瀏覽器引擎會自動適配至Webkit |
iOS | iOS系統的混合應用,瀏覽器引擎會自動適配至Webkit |
WinPhone | Windows Phone系統的混合應用,瀏覽器引擎會自動適配至Trident |
PC | 桌面應用,采用CEF做為容器,瀏覽器引擎會自動適配至Webkit |
平臺適配
AOP(Aspect-Oriented Programming):面向切面的編程范式,其核心思想是將橫切關注點從主關注點中分離出來,因此特定領域的問題代碼可以從標準業務邏輯中分離出來,從而使得主業務邏輯和領域性業務邏輯之間不會存在任何耦合性。
這里我們可以借鑒AOP思想來實現平臺的適配策略,結合不同的平臺實現邏輯,我們可以認為對于使用規范、標準來實現業務邏輯的部分為我們的主關注點,而不同平臺可以做為若干的切面關注點進行封裝,各平臺只需關注自己平臺下對標準的修正邏輯即可,因此可以通過增加、刪除平臺修正的切面邏輯來實現對不同平臺的適配。
實現時我們首先提取標準業務邏輯,然后各平臺根據實際情況實現對業務邏輯的修正:
- 標準業務邏輯:主關注點,這里主要是使用根據W3C、ES標準來實現的業務邏輯
- 前置平臺修正邏輯:領域特定關注點,主要是根據平臺特性對標準在該平臺下的修正,修正邏輯會先于標準邏輯執行
- 后置平臺修正邏輯:同前置平臺修正邏輯,也是領域特定關注點,修正邏輯會在標準邏輯執行后再執行
根據此思路我們對比以下兩段代碼:
代碼一:目前常用的平臺適配方式
function doSomething(){ if(isTrident){ // TODO trident implement }else if(isWebkit){ // TODO webkit implement }else if(isGecko){ // TODO gecko implement }else if(isPresto){ // TODO presto implement }else{ // TODO w3c implement } } // 上層應用使用 doSomething(1,2,3);
此方式對所有平臺的修正邏輯均在主邏輯中實現,存在以下弊端:
- 對平臺特有的修正邏輯耦合在主邏輯中,平臺特有的更新必然引起主邏輯的更新
- 對于新增或刪除平臺的支持必須修改到主業務邏輯
- 無法分離不必要的平臺修正,比如基于webkit引擎的移動平臺應用不需要其他平臺的修正邏輯
代碼二:借鑒AOP思想的平臺適配方式
function doSomething(){ // TODO w3c/es implement } // 上層應用使用 doSomething(1,2,3);
針對Trident平臺適配的邏輯,比如 trident.js中
// trident implement doSomething = doSomething._$aop( function(_event){ // TODO trident implement }, function(_event){ // TODO trident implement } );
對比代碼一,我們可以發現借鑒AOP思想的接口適配方式分離了標準業務邏輯和平臺特有業務邏輯,是否增加平臺特有業務邏輯并不會影響主業務邏輯的執行,而對于平臺修正邏輯的切入則可以直接通過配置的方式靈活的進行增刪,因此我們可以從中得到以下好處:
- 主邏輯和平臺特有邏輯無耦合性,可隨意分離、整合
- 對于新增平臺適配只需新加平臺特有邏輯即可,而無需影響到主業務邏輯
- 可通過配置控制支持的目標平臺,有選擇性的導出平臺特有業務邏輯
實現舉例
NEJ框架借鑒AOP思想提供了配置式的平臺適配系統,對于這部分的詳細信息可參閱NEJ的《依賴管理系統》和《平臺適配系統》了解更為詳細的信息,以下僅舉例說明NEJ中適配的使用方式。
一個典型的適配控件結構如下圖所示:
這里的widget.js是控件業務邏輯實現文件,在此控件的實現中會依賴到存在平臺差異的API,其依賴代碼如下所示
NEJ.define([ 'util/event', '{platform}api.js' ],function(t,h,p){ // TODO });
這里對 {platform}api.js 的處理方式如下圖所示,這里的./相對于當前的代碼文件即widget.js文件所在的目錄
這里的api.js文件為需平他適配API的標準實現邏輯,而api.patch.js文件則利用NEJ.patch接口對各平臺做按需適配邏輯,同時打包時也根據NEJ.patch接口中對平臺的條件識別做按需輸出,由于api.patch.js文件最終會按需輸出,因此在此文件中除了使用NEJ.patch做平臺適配邏輯外,不允許包含其它業務邏輯。
// 此文件只能定義NEJ.patch不可執行其他業務邏輯 // 打包輸出時僅根據平臺配置輸出所需處理邏輯 // 實際情況看需求,可將平臺相關部分邏輯獨立到單獨的模塊中 NEJ.define([ './hack.js' ],function(h){ // 針對trident平臺的處理邏輯 NEJ.patch('TR',function(){ // TODO }); // 針對gecko平臺的處理邏輯 NEJ.patch('GR',[ './hack.firefox.js' ],function(fh){ // TODO }); // 針對IE6平臺的處理邏輯 NEJ.patch('TR==2.0',['./hack.ie6.js']); // 針對IE7-IE9的處理邏輯 NEJ.patch('3.0<=TR<=5.0',function(){ // TODO }); // 這里必須同hack.js文件的返回值一致 return h; });
最后我們只需要配置產品的目標平臺即可輸出平臺對應的適配,而不會存在其他平臺的額外影響:
<script src="/path/to/nej/define.js?p=wkgktd"></script> <script src="/path/to/nej/define.js?p=cef"></script>
平臺變更
通過以上實現舉例我們可以看到當平臺發生變更時我們可以快速進行擴展或縮減
平臺擴展
當有新平臺需要作為系統目標平臺時,我們只需要做以下工作:
- 增加平臺配置識別符,如nxw
- 識別該平臺與標準存在的差異,增加平臺特有業務邏輯至patch
-
系統對平臺配置部分增加新添的識別符,如
原平臺適配:<script src="/path/to/nej/define.js?p=wkgktd"></script>
新增平臺適配:<script src="/path/to/nej/define.js?p=wkgktdnxw"></script>
即可完成對平臺的擴展,而不會影響到原有的業務邏輯。
平臺縮減
當系統適配的目標平臺由于某種原因退出歷史舞臺時,系統也需要將該平臺的冗余代碼從系統中剔除,我們只需要做以下工作:
-
系統對平臺配置部分刪除要剔除的平臺標識,如:
原平臺適配:<script src="/path/to/nej/define.js?p=wkgktd"></script>
縮減后平臺適配:<script src="/path/to/nej/define.js?p=wk"></script>
即可完成對平臺的縮減,而無需修改任何業務邏輯。
以上即是有關平臺可擴展性的介紹。下一篇將闡述模塊的可擴展性,敬請期待!
本作品采用知識共享署名 4.0 國際許可協議進行許可。
留言列表