2.3.2 體系結構模式
體系結構模式構建在上述討論過的相對原始的體系結構元素之上,提供組合的、重復出現的結構,這些結構在給定的環境中能運行良好。它們未必是完整的解決方案,但當與其他模式組合時,它們會更好地引導設計者給出一個給定問題域的解決方案。
這是一個大的主題,已經有了許多用于分布式系統的體系結構模式。本節中,我們給出分布式系統中幾個關鍵的體系結構模型,包括分層體系結構(layering architecture)、層次化體系結構(tiered architecture)和瘦客戶相關的概念(包括虛擬網絡計算的特定機制)。我們也把Web服務當做一個體系結構模式進行了考察,給出了其他可以應用在分布式系統中的模式。
分層 分層的概念是一個熟悉的概念,與抽象緊密相關。在分層方法中,一個復雜的系統被分成若干層,每層利用下層提供的服務。因此,一個給定的層提供一個軟件抽象,更高的層不清楚實現細節,或不清楚在它下面的其他層。
就分布式系統而言,這等同于把服務垂直組織成服務層。一個分布式服務可由一個或多個服務器進程提供,這些進程相互交互,并與客戶進程交互,維護服務中的資源在系統范圍內的一致視圖。例如,在互聯網上基于網絡時間 圖2-7 分布式系統中軟件和硬件服務層協議(Network Time Protocol,NTP)可實現一個網絡時間服務,其中,服務器進程運行在互聯網的主機上,給任一發出請求的客戶提供當前的時間,51作為與服務器交互的結果,客戶調整它們的當前時間。給定分布式系統的復雜性,這些服務組織成若干層經常是有幫助的。圖2-7給出了一個分層體系結構的常規視圖,并在第3~6章詳細敘述這個視圖的細節。
圖2-7引入了重要的術語——平臺和中間件,具體定義如下:
- 一個服務于分布式系統和應用的平臺由最底層的硬件和軟件層組成。這些底層為其上層提供服務,它們在每個計算機中都是獨立實現的,提供系統的編程接口,方便進程之間的通信和協調。主要的例子有Intel x86/Windows、Intel x86/Solaris、Intel x86/Mac OS X、Intel x86/Linux和ARM/Symbian。
- 1.5.1節把中間件定義成一個軟件層,其目的是屏蔽異構性,給應用程序員提供方便的編程模型。中間件表示成一組計算機上的進程或對象,這些進程或對象相互交互,實現分布式應用的通信和資源共享支持。中間件提供有用的構造塊,構造在分布式系統中一起工作的軟件組件。特別的,它通過對抽象的支持,如遠程方法調用、進程組之間的通信、事件的通知、共享數據對象在多個協作的計算機上的分布、放置和檢索、共享數據對象的復制以及多媒體數據的實時傳送,提升應用程序通信活動的層次。我們將在下面的2.3.3節講述這個重要的話題。
層次化體系結構 層次化體系結構與分層體系結構是互補的。分層將服務垂直組織成抽象層,而層次化是一項組織給定層功能的技術,它把這個功能放在合適的服務器上,或者作為第二選擇放在物理結點上。這個技術與圖2-7中所示的應用和服務的組織最相關,但它也可以應用到一個分布式系統體系結構的所有層。
我們先查看兩層和三層體系結構概念。為了說明這些概念,考慮如下對一個給定應用的功能分解:
- 表示邏輯,涉及處理用戶交互和修改呈現給用戶的應用視圖;
- 應用邏輯,涉及與應用相關的(也稱為業務邏輯,雖然這個概念不僅僅限于業務應用)詳細的應用特定處理;
- 數據邏輯,涉及應用的持久存儲,通常在一個數據庫管理系統中。
現在考慮用客戶-服務器技術實現這樣一個應用。圖2-8a和圖2-8b分別給出了相關的兩層和三層體系結構解決方案,以便于比較。
在兩層解決方案中,上面提及的三個方面必須被分到兩個進程(客戶和服務器)中。通常通過分隔應用邏輯來完成這個劃分,把一些應用邏輯放在客戶端,剩下的放在服務器端(雖然其他解決方案也是可以的)。這個模式的好處是具有交互的低延遲,僅有調用操作的消息交換,不足是將應用邏輯分離到不同的進程,帶來的后果是一部分邏輯不能被另一部分直接調用。
在三層解決方案中,有從邏輯元素到物理服務器的一對一映射,因此,例如,應用邏輯放在一個地方,能提高軟件的可維護性。每一層也都有定義明確的角色,例如,第三層僅僅是一個提供(可能是標準的)關系服務接口的數據庫。第一層也可以是一個簡單的用戶界面,提供對瘦客戶的內在支持(見下面的討論)。缺點是增加了管理三個服務器的復雜性,也增加了與每個操作相關的網絡流量和延遲。
注意這個方案可以推廣到n層(或多層)的解決方案,其中一個給定的應用領域劃分為n個邏輯元素,每個邏輯元素映射到一個給定的服務器元素。以維基百科基于Web的可供公眾編輯的百科全書為例,它采用了多層次體系結構來處理大量的Web請求(每秒請求高達60000頁)。
AJAX的作用:在1.6節中,我們介紹了AJAX(Asynchronous Javascript And XML)是Web所使用的標準客戶-服務器交互方式的擴展。AJAX滿足了Javascript前端程序(運行在Web瀏覽器中)和基于服務器的后端程序(擁有描述應用狀態的數據)之間的細粒度通信的需要。概括而言,在標準的Web交互方式中,瀏覽器發送HTTP請求給服務器,請求給定URL的頁面、圖像或其他資源。服務器發送整個頁面作為應答,這個頁面或者從服務器上的一個文件中讀取,或者由一個程序生成,取決于URL中可識別的資源類型。當客戶收到內容時,瀏覽器根據其MIME類型(text/html、image/jpg等)相關的顯示方式呈現它。雖然Web頁面由不同類型的內容項組成,但是整個頁面以它在html頁面定義中指定的方式由瀏覽器組合并呈現。
這種標準的交互方式在幾個重要的方面約束了Web應用的開發:
- 一旦瀏覽器發送了一個請求新Web頁面的http請求,用戶不能與該頁面交互,直到新的html內容被瀏覽器收到并呈現。這個時間間隔是不確定的,因為它受限于網絡和服務器延遲。
- 為了用來自服務器的額外數據修改當前頁面的一小部分,也要請求和顯示整個新的頁面。這導致了對用戶應答的延遲、客戶和服務器兩端的額外處理以及冗余的網絡流量。
- 客戶顯示的頁面內容不能被更新,從而不能響應服務器端擁有的應用數據的變化。
Javascript是一個跨平臺、跨瀏覽器的編程語言,它能下載到瀏覽器中并執行,它的引入是去除這些約束的第一步。Javascript是一個通用的語言,它使得用戶接口和應用邏輯能在瀏覽器窗口中被編程和執行。
AJAX是使得開發和部署交互型Web應用成為可能的第二步,它使得Javascript前端程序能直接從服務器程序中獲得新的數據。任何數據項都能被請求,當前頁有選擇地更新來顯示新的值。甚至,前端能以對應用有用的任何方式響應新的數據。
許多Web應用允許用戶訪問和更新大量共享的數據集,這些數據可能會改變以響應其他客戶的輸入或服務器收到的數據輸入。它們要求一個及時的前端組件(運行在每個客戶瀏覽器中)來完成用戶接口動作(如菜單選擇),也請求訪問一個必須放在服務器上供共享的數據集。這樣的數據集通常太大并且是動態的,所以不允許使用基于在用戶會話(用于客戶操縱)開始時下載整個應用狀態副本給客戶并供其操作的體系結構。
圖2-9 AJAX舉例:更新足球比分AJAX是支持構建這樣的應用的“膠水”,它提供一套通信機制,使得運行在一個瀏覽器中的前端組件能發送請求,并從運行在服務器上的后端組件接收結果。客戶通過Javascript XmlHttpRequest對象發送請求,該對象管理與一個服務器進程的HTTP交互(見1.6節)。因為XmlHttpRequest有一個復雜的API,且該API有些依賴瀏覽器,所以,通常通過眾多可用于支持Web應用開發的Javascript庫中的一個庫訪問它。圖2-9展示了ATAX在Prototype.js Javascript庫中的使用[www.prototypejs.org]。
這個例子是一個Web應用的片段,該應用顯示足球比賽最新積分的頁面。用戶單擊頁面的相關行,55可以請求獲得單個比賽的分數更新,其對應著執行示例程序的第一行。Ajax.Request對象發送一個HTTP請求給scores.php程序,該程序與Web頁面位于相同的服務器上。Ajax.Request對象接著返回控制,允許瀏覽器繼續應答相同窗口或其他窗口中其他用戶的動作。當scores.php程序已經獲得了最新的比分時,它在一個HTTP應答中返回該比分,因為它是一個onSuccess動作,所以,它分析結果并把比分插入到當前頁面的相關位置。頁面的其余部分不受影響,不被重載入。
這說明了在第一層組件和第二層組件之間使用的通信類型。雖然Ajax.Request(和下層的XmlHttpRequest對象)提供同步和異步通信,但總是使用異步版本,因為用戶界面對延遲的服務器應答是不可接受的。
這個簡單的例子說明了在兩層應用中AJAX的使用。在三層應用中,服務器組件(在我們的例子中是scores.php)將發送一個請求給數據管理器組件(通常是發給數據庫服務器的一個SQL查詢)用于請求數據。這個請求是異步的,因為沒有理由直到請求被滿足后才返回控制給服務器。
AJAX機制組成了一項有效的技術,用于在具有不確定延遲的互聯網環境下構造及時的Web應用,它已經得到了非常廣泛的使用。Google地圖應用[www.google.com Ⅱ]是一個突出的例子。地圖作為一個連續的256×256像素圖像(稱為圖片(tile))數組顯示。當地圖被移動時,瀏覽器中的Javascript代碼重定位可見的圖片,需要填入可見區域的額外的圖片,可以通過AJAX調用到Google服務器去獲取。圖片一經收到就會顯示出來,但瀏覽器在等待的時候可以繼續應答用戶的交互。
瘦客戶 分布式計算的趨勢是將復雜性從最終用戶設備移向互聯網服務。這點在向云計算(見第1章)發展的趨勢中最明顯,在上面討論的層次化體系結構中也能看到。這個趨勢導致了對瘦客戶概念的興趣,它使得能以很少的對客戶設備的假設或需求,獲得對復雜網絡化服務的訪問,這些服務可以通過云解決方案提供。更具體來說, 圖2-10 瘦客戶和計算機服務器術語瘦客戶指的是一個軟件層,在執行一個應用程序或訪問遠程計算機上的服務時,由該軟件層提供一個基于窗口的本地用戶界面。例如,圖2-10給出了一個瘦客戶,它在訪問互聯網上的一臺計算服務器。這種方法的好處是有可能通過大量的網絡化服務和潛在能力極大地增加簡單的本地設備(例如,智能電話和其他資源有限的設備)。56瘦客戶體系結構的主要缺點是:在交互頻繁的圖形活動(如CAD和圖像處理)中,因為網絡和操作系統的延遲,用戶感受到的延遲會因為在瘦客戶和應用進程之間傳輸圖像和向量信息而增大到不可接受的程度。
這個概念導致虛擬網絡計算(Virtual Network Computing,VNC)的出現。該項技術首先由Olivetti和Oracle研究實驗室的研究者引入[Richardson et al.1998]。初始的概念已經演化成實現,例如,RealVNC[www.realvnc.com]提供了一個軟件解決方案,Adventiq[www.adventiq.com]提供了一個基于硬件的解決方案,該方案支持在IP上傳送鍵盤、視頻和鼠標事件(KVM-over-IP)。其他VNC實現包括Apple Remote Desktop、TightVNC和Aqua Connect。
VNC在概念上是簡單的,即為遠程訪問提供圖形用戶界面。在這個解決方案中,VNC客戶(觀眾)通過VNC協議與VNC服務器交互。從圖形支持角度看,協議在原語層次上操作,基于幀緩沖區,以以下操作為特色:在屏幕上的給定位置放置矩形像素數據(一些解決方案如Citrix的XenApp從窗口操作方面來看在較高層次操作[www.citrix.com])。這種低層方法確保協議能工作在任何操作系統或應用中。雖然這很直接,但它隱含著用戶能用不同設備從任何地方訪問他們的計算機設施,這代表了在移動計算方面邁出的重要的一步。
虛擬網絡計算已經取代了網絡計算機,后者是以前的瘦客戶解決方案的實現方法,它通過簡單、廉價、完全依賴網絡化服務的硬件設備,從遠程文件服務器下載它們的操作系統和用戶所需的應用軟件。因為所有的應用數據和代碼由一個文件服務器存儲,所以,用戶可以從一個網絡計算機遷移到另一個。事實上,虛擬網絡計算被證明是一個更靈活的解決方案,現在主宰著市場。
其他經常出現的模式 如上所述,現在已有大量的體系結構模式,且它們已被文檔化。這里給出一些關鍵的例子。
- 代理(proxy)模式是分布式系統中經常出現的模式,其主要用于支持遠程過程調用或遠程方法調用的位置透明性。用這種方法,一個代理在本地地址空間中被創建,用于代表遠程對象。這個代理提供與遠程對象一樣的接口,程序員調用這個代理對象,因此無須了解交互的分布式特性。在RPC和RMI中,代理支持位置透明性的作用將在第5章做進一步的討論。注意代理也被用于封裝其他的功能(諸如復制或緩存的放置策略等)。
- Web服務中的業務代理(brokerage)的使用能被看成是一個在可能很復雜的分布式基礎設施中支持互操作性的體系結構模式。特別地,57這個模式是由服務提供商、服務請求者和服務代理(提供與請求的服務一致的服務)三部分組成,如圖2-11所示。這個業務代理模式在分布式系統的多個領域被多次應用,例如Java RMI中的注冊服務、CORBA中的名字服務(分別參見第5章和第8章的討論)。 圖2-11 Web服務體系結構模式
- 反射(reflection)模式在分布式系統中作為支持內省(系統的動態發現的特性)和從中調停(動態修改結構或行為的能力)的手段而被持續地使用。例如,Java的內省能力被用于RMI的實現中,提供通用的分發(參見5.4.2節的討論)。在一個反射系統中,標準的服務接口在基礎層可供使用,但元層接口也可以提供對涉及服務實現的組件及組件參數的訪問。許多技術在元層可用,包括截獲到達的消息或調用、動態發現由給定對象提供的接口、發現和適應系統底層體系結構的能力。反射被應用于分布式系統中的多個領域,特別是反射中間件領域,例如,可以用于支持更多的可配置及重配置中間件體系結構[Kon et al.2001]。
與分布式系統相關的體系結構模式更多的例子可以在Bushmann等人[2007]的著作中找到。