軟件架構之架構風格
- 9.3 軟件架構風格
- 9.3.1 軟件架構風格分類
- 9.3.2 數據流風格
- 9.3.3 調用/返回風格
- 9.3.4 獨立構件風格
- 9.3.5 虛擬機風格
- 9.3.6 倉庫風格
- 9.4 層次系統架構風格
- 9.4.1 二層及三層 C/S 架構風格
- 9.4.2 B/S 架構風格
- 9.4.3 MVC 架構風格
- 9.4.4 MVP 架構風格
- 9.5 面向服務的架構
- 9.5.1 SOA 概述
- 9.5.2 SOA 的關鍵技術
- 9.5.3 SOA 的實現方法
- 9.5.4 微服務
9.3 軟件架構風格
軟件架構設計的一個核心問題是能否使用重復的軟件架構模式,即能否達到架構級別的軟件重用。也就是說,能否在不同的軟件系統中,使用同一架構。基于這個目的,學者們開始研究和實踐軟件架構的風格和類型問題。
軟件架構風格是描述某一特定應用領域中系統組織方式的慣用模式(idiomatic paradigm)。架構風格定義了一個系統家族,即一個架構定義一個詞匯表和一組約束。詞匯表中包含一些構件和連接件類型,而這組約束指出系統是如何將這些構件和連接件組合起來的。架構風格反映了領域中眾多系統所共有的結構和語義特性,并指導如何將各個模塊和子系統有效地組織成一個完整的系統。按這種方式理解,軟件架構風格定義了用于描述系統的術語表和一組指導構建系統的規則。
對軟件架構風格的研究和實踐促進了對設計的重用,一些經過實踐證實的解決方案也可以可靠地用于解決新的問題。架構風格不變的部分使不同的系統可以共享同一個實現代碼。只要系統是使用常用的、規范的方法來組織,就可使別的設計者很容易地理解系統的架構。
例如,如果某人把系統描述為客戶/服務器模式,則不必給出設計細節,我們立刻就會明白系統是如何組織和工作的。軟件架構風格為大粒度的軟件重用提供了可能。然而,對于應用架構風格來說,由于視點的不同,系統設計師有很大的選擇余地。要為系統選擇或設計某一個架構風格,必須根據特定項目的具體特點,進行分析比較后再確定,架構風格的使用幾乎完全是特定的。
9.3.1 軟件架構風格分類
討論架構風格時要回答的問題是:
(1)設計詞匯表是什么?
(2)構件和連接件的類型是什么?
(3)可容許的結構模式是什么?
(4)基本的計算模型是什么?
(5)風格的基本不變性是什么?
(6)其使用的常見例子是什么?
(7)使用此風格的優缺點是什么?
(8)其常見的特例是什么?
這些問題的回答包括了架構風格的最關鍵的四要素內容,即提供一個詞匯表、定義一套配置規則、定義一套語義解釋原則和定義對基于這種風格的系統所進行的分析。Garlan 和Shaw 根據此框架給出了通用架構風格的分類:
(1)數據流風格:批處理序列;管道/過濾器。
(2)調用/返回風格:主程序/子程序;面向對象風格;層次結構。
(3)獨立構件風格:進程通信;事件系統。
(4)虛擬機風格:解釋器;基于規則的系統。
(5)倉庫風格:數據庫系統;超文本系統;黑板系統。
9.3.2 數據流風格
數據流風格的軟件架構是一種最常見,結構最為簡單的軟件架構。這樣的架構下,所有的數據按照流的形式在執行過程中前進,不存在結構的反復和重構,就像工廠中的汽車流水線一樣,數據就像汽車零部件一樣在流水線的各個節點上被加工,最終輸出所需要的結果(一部完整的汽車)。在流動過程中,數據經過序列間的數據處理組件進行處理,然后將處理結果向后傳送,最后進行輸出。
數據流風格架構主要包括兩種具體的架構風格:批處理序列和管道-過濾器。
- 批處理序列
批處理風格的每一步處理都是獨立的,并且每一步是順序執行的。只有當前一步處理完,后一步處理才能開始。數據傳送在步與步之間作為一個整體。(組件為一系列固定順序的計算單元,組件間只通過數據傳遞交互。每個處理步驟是一個獨立的程序,每一步必須在前一步結束后才能開始,數據必須是完整的,以整體的方式傳遞)批處理的典型應用:
(1)經典數據處理;
(2)程序開發;
(3)Windows 下的 BAT 程序就是這種應用的典型實例。
- 管道和過濾器
在管道/過濾器風格的軟件架構中,每個構件都有一組輸入和輸出,構件讀輸入的數據流,經過內部處理,然后產生輸出數據流。這個過程通常通過對輸入流的變換及增量計算來完成,所以在輸入被完全消費之前,輸出便產生了。因此,這里的構件被稱為過濾器,這種風格的連接件就像是數據流傳輸的管道,將一個過濾器的輸出傳到另一過濾器的輸入。
此風格特別重要的過濾器必須是獨立的實體,它不能與其他的過濾器共享數據,而且一個過濾器不知道它上游和下游的標識。一個管道/過濾器網絡輸出的正確性并不依賴于過濾器進行增量計算過程的順序。
圖 9-5 是管道/過濾器風格的示意圖。一個典型的管道/過濾器架構的例子是以 UNIX shell 編寫的程序。UNIX 既提供一種符號,以連接各組成部分(UNIX 的進程),又提供某種進程運行時機制以實現管道。另一個著名的例子是傳統的編譯器。傳統的編譯器一直被認為是一種管道系統,在該系統中,一個階段(包括詞法分析、語法分析、語義分析和代碼生成)的輸出是另一個階段的輸入。
管道/過濾器風格的軟件架構具有許多很好的特點:
(1)使得軟構件具有良好的隱蔽性和高內聚、低耦合的特點;
(2)允許設計者將整個系統的輸入/輸出行為看成是多個過濾器的行為的簡單合成;
(3)支持軟件重用。只要提供適合在兩個過濾器之間傳送的數據,任何兩個過濾器都可被連接起來;
(4)系統維護和增強系統性能簡單。新的過濾器可以添加到現有系統中來;舊的可以被改進的過濾器替換掉;
(5)允許對一些如吞吐量、死鎖等屬性的分析;
(6)支持并行執行。每個過濾器是作為一個單獨的任務完成,因此可與其他任務并行執行。
但是,這樣的系統也存在著若干不利因素。
(1)通常導致進程成為批處理的結構。這是因為雖然過濾器可增量式地處理數據,但它們是獨立的,所以設計者必須將每個過濾器看成一個完整的從輸入到輸出的轉換;
(2)不適合處理交互的應用。當需要增量地顯示改變時,這個問題尤為嚴重;
(3)因為在數據傳輸上沒有通用的標準,每個過濾器都增加了解析和合成數據的工作,這樣就導致了系統性能下降,并增加了編寫過濾器的復雜性。
- 批處理序列風格與管道過濾器風格對比
- 共同點:把任務分成一系列固定順序的計算單元(組件)。組件間只通過數據傳遞交互。
- 區別:批處理是全部的、高潛伏性的,輸入時可隨機存取,無合作性、無交互性。而管道過濾器是遞增的,數據結果延遲小,輸入時處理局部化,有反饋、可交互。批處理強調數據傳送在步與步之間作為一個整體,而管理過濾器無此要求。
9.3.3 調用/返回風格
調用返回風格顧名思義,就是指在系統中采用了調用與返回機制。利用調用-返回實際上是一種分而治之的策略,其主要思想是將一個復雜的大系統分解為一些子系統,以便降低復雜度,并且增加可修改性。程序從其執行起點開始執行該構件的代碼,程序執行結束,將控制返回給程序調用構件。
調用/返回風格架構主要包括三種具體的架構風格:主程序/子程序;面向對象風格;層次結構。
-
主程序/子程序
主程序/子程序風格是結構化開發時期的經典架構風格。這種風格一般采用單線程控制,把問題劃分為若干處理步驟,構件即為主程序和子程序。子程序通常可合成為模塊。過程調用作為交互機制,即充當連接件。調用關系具有層次性,其語義邏輯表現為子程序的正確性,取決于它調用的子程序的正確性。 -
面向對象風格
抽象數據類型概念對軟件系統有著重要作用,目前軟件界已普遍使用面向對象系統。這種風格建立在數據抽象和面向對象的基礎上,數據的表示方法和它們的相應操作封裝在一個抽象數據類型或對象中。這種風格的構件是對象,或者說是抽象數據類型的實例。對象是一種被稱作管理者的構件,因為它負責保持資源的完整性。對象是通過函數和過程的調用來交互的。
圖 9-6 是數據抽象和面向對象風格的示意圖。
這種風格的兩個重要特征為:
(1)對象負責維護其表示的完整性;
(2)對象的表示對其他對象而言是隱蔽的。因為一個對象對它的客戶隱藏了自己的表示,所以這些對象可以不影響它的客戶就能改變其實現方法。面向對象的系統有許多優點,并早已為人所知:
(1)因為對象對其他對象隱藏它的表示,所以可以改變一個對象的表示,而不影響其他的對象;
(2)設計者可將一些數據存取操作的問題分解成一些交互的代理程序的集合。 但是,面向對象的系統也存在著某些問題:
(1)為了使一個對象和另一個對象通過過程調用等進行交互,必須知道對象的標識。只要一個對象的標識改變了,就必須修改所有其他明確調用它的對象;
(2)必須修改所有顯式調用它的其他對象,并消除由此帶來的一些副作用。例如,如果 A 使用了對象 B,C 也使用了對象 B,那么,C 對 B 的使用所造成的對 A 的影響可能是料想不到的。
- 層次結構風格
層次系統組織成一個層次結構,每一層為上層服務,并作為下層客戶。在一些層次系統中,除了一些精心挑選的輸出函數外,內部的層只對相鄰的層可見。這樣的系統中構件在一些層實現了虛擬機(在另一些層次系統中層是部分不透明的)。連接件通過決定層間如何交互的協議來定義,拓撲約束包括對相鄰層間交互的約束。這種風格支持基于可增加抽象層的設計。這樣,允許將一個復雜問題分解成一個增量步驟序列的實現。由于每一層最多只影響兩層,同時只要給相鄰層提供相同的接口,允許每層用不同的方法實現,同樣為軟件重用提供了強大的支持。
圖 9-7 是層次系統風格的示意圖。層次系統最廣泛的應用是分層通信協議。在這一應用領域中,每一層提供一個抽象的功能,作為上層通信的基礎。較低的層次定義低層的交互,最低層通常只定義硬件物理連接。
層次系統有許多可取的屬性:
(1)支持基于抽象程度遞增的系統設計,使設計者可以把一個復雜系統按遞增的步驟進行分解;
(2)支持功能增強,因為每一層至多和相鄰的上下層交互,因此功能的改變最多影響相鄰的上下層;
(3)支持重用。只要提供的服務接口定義不變,同一層的不同實現可以交換使用。這樣,就可以定義一組標準的接口,而允許各種不同的實現方法。
但是,層次系統也有其不足之處:
(1)并不是每個系統都可以很容易地劃分為分層的模式,甚至即使一個系統的邏輯結構是層次化的,出于對系統性能的考慮,系統設計師不得不把一些低級或高級的功能綜合起來;
(2)很難找到一個合適的、正確的層次抽象方法。
9.3.4 獨立構件風格
獨立構件風格主要強調系統中的每個構件都是相對獨立的個體,它們之間不直接通信,以降低耦合度,提升靈活性。獨立構件風格主要包括:進程通訊和事件系統子風格。
- 進程通信架構風格進程通信架構風格:構件是獨立的過程,連接件是消息傳遞。這種風格的特點是構件通常是命名過程,消息傳遞的方式可以是點到點、異步和同步方式及遠過程調用等。
2 事件系統風格基于事件的隱式調用風格的思想是構件不直接調用一個過程,而是觸發或廣播一個或多個事件。系統中的其他構件中的過程在一個或多個事件中注冊,當一個事件被觸發,系統自動調用在這個事件中注冊的所有過程,這樣,一個事件的觸發就導致了另一模塊中的過程的調用。
從架構上說,這種風格的構件是一些模塊,這些模塊既可以是一些過程,又可以是一些事件的集合。過程可以用通用的方式調用,也可以在系統事件中注冊一些過程,當發生這些事件時,過程被調用。
基于事件的隱式調用風格的主要特點是事件的觸發者并不知道哪些構件會被這些事件影響。這樣不能假定構件的處理順序,甚至不知道哪些過程會被調用,因此,許多隱式調用的系統也包含顯式調用作為構件交互的補充形式。
支持基于事件的隱式調用的應用系統很多。例如,在編程環境中用于集成各種工具,在數據庫管理系統中確保數據的一致性約束,在用戶界面系統中管理數據,以及在編輯器中支持語法檢查。例如在某系統中,編輯器和變量監視器可以登記相應 Debugger 的斷點事件。
當 Debugger 在斷點處停下時,它聲明該事件,由系統自動調用處理程序,如編輯程序可以卷屏到斷點,變量監視器刷新變量數值。而 Debugger 本身只聲明事件,并不關心哪些過程會啟動,也不關心這些過程做什么處理。
隱式調用系統的主要優點有:
(1)為軟件重用提供了強大的支持。當需要將一個構件加入現存系統中時,只需將它注冊到系統的事件中。
(2)為改進系統帶來了方便。當用一個構件代替另一個構件時,不會影響到其他構件的接口。
隱式調用系統的主要缺點有:
(1)構件放棄了對系統計算的控制。一個構件觸發一個事件時,不能確定其他構件是否會響應它。而且即使它知道事件注冊了哪些構件的過程,它也不能保證這些過程被調用的順序。
(2)數據交換的問題。有時數據可被一個事件傳遞,但另一些情況下,基于事件的系統必須依靠一個共享的倉庫進行交互。在這些情況下,全局性能和資源管理便成了問題。
(3)既然過程的語義必須依賴于被觸發事件的上下文約束,關于正確性的推理存在問題。
9.3.5 虛擬機風格
虛擬機風格的基本思想是人為構建一個運行環境,在這個環境之上,可以解析與運行自定義的一些語言,這樣來增加架構的靈活性,虛擬機風格主要包括解釋器和規則為中心兩種架構風格。
1.解釋器
一個解釋器通常包括完成解釋工作的解釋引擎,一個包含將被解釋的代碼的存儲區,一個記錄解釋引擎當前工作狀態的數據結構,以及一個記錄源代碼被解釋執行進度的數據結構。
具有解釋器風格的軟件中含有一個虛擬機,可以仿真硬件的執行過程和一些關鍵應用。解釋器通常被用來建立一種虛擬機以彌合程序語義與硬件語義之間的差異。其缺點是執行效率較低。典型的例子是專家系統。
- 規則為中心
基于規則的系統包括規則集、規則解釋器、規則/數據選擇器及工作內存。
9.3.6 倉庫風格
在倉庫(repository)風格中,有兩種不同的構件:中央數據結構說明當前狀態,獨立構件在中央數據存儲上執行,倉庫與外構件間的相互作用在系統中會有大的變化。
倉庫風格包括的子風格有:數據庫系統、超文本系統、黑板風格。
數據庫架構是庫風格最常見的形式。構件主要有兩大類,一個是中央共享數據源,保存當前系統的數據狀態;另一個是多個獨立處理元素,處理元素對數據元素進行操作。而超文本系統的典型代表,就是早期的靜態網頁。三種架構子風格中,最復雜的是黑板系統。
黑板系統是在抽象與總結語言理解系統 HEARSAY-11 的基礎上產生的,適合于解決復雜的非結構化的問題,能在求解過程中綜合運用多種不同知識源,使得問題的表達、組織和求解變得比較容易。黑板系統是一種問題求解模型,是組織推理步驟、控制狀態數據和問題求解之領域知識的概念框架。它將問題的解空間組織成一個或多個應用相關的分級結構。分級結構的每一層信息由一個唯一的詞匯來描述,它代表了問題的部分解。領域相關的知識被分成獨立的知識模塊,它將某一層次中的信息轉換成同層或相鄰層的信息。各種應用通過不同知識表達方法、推理框架和控制機制的組合來實現。影響黑板系統設計的最大因素是應用問題本身的特性,但是支撐應用程序的黑板體系結構有許多相似的特征和構件。對于特定應用問題,黑板系統可通過選取各種黑板、知識源和控制模塊的構件來設計;
也可以利用預先定制的黑板體系結構的編程環境。圖 9-8 是黑板系統的組成。黑板系統的傳統應用是信號處理領域,如語音和模式識別。另一應用是松耦合代理數據共享存取。
我們從圖 9-8 中可以看出,黑板系統主要由三部分組成:
(1)知識源。知識源中包含獨立的、與應用程序相關的知識,知識源之間不直接進行通信,它們之間的交互只通過黑板來完成。
(2)黑板數據結構。黑板數據是按照與應用程序相關的層次來組織的解決問題的數據,知識源通過不斷地改變黑板數據來解決問題。
(3)控制。控制完全由黑板的狀態驅動,黑板狀態的改變決定使用的特定知識。
9.4 層次系統架構風格
本章 9.3.3 節中已對層次系統架構風格進行了初步的介紹,下面將對幾種經典的層次風格進行詳細說明。
9.4.1 二層及三層 C/S 架構風格
C/S 架構是基于資源不對等,且為實現共享而提出來的,是 20 世紀 90 年代成熟起來的技術,C/S 結構將應用一分為二,服務器(后臺)負責數據管理,客戶機(前臺)完成與用戶的交互任務。
C/S 軟件架構具有強大的數據操作和事務處理能力,模型思想簡單,易于人們理解和接受。但隨著企業規模的日益擴大,軟件的復雜程度不斷提高,傳統的二層 C/S 結構存在以下幾個局限:
二層 C/S 結構為單一服務器且以局域網為中心,所以難以擴展至大型企業廣域網或 Internet;軟、硬件的組合及集成能力有限;
服務器的負荷太重,難以管理大量的客戶機,系統的性能容易變壞;
數據安全性不好。因為客戶端程序可以直接訪問數據庫服務器,那么,在客戶端計算機上的其他程序也可想辦法訪問數據庫服務器,從而使數據庫的安全性受到威脅。
正是因為二層 C/S 有這么多缺點,因此,三層 C/S 結構應運而生。三層 C/S 結構是將應用功能分成表示層、功能層和數據層三個部分,如圖 9-9 所示。
表示層是應用的用戶接口部分,它擔負著用戶與應用間的對話功能。它用于檢查用戶從鍵盤等輸入的數據,并顯示應用輸出的數據。在變更用戶接口時,只需改寫顯示控制和數據檢查程序,而不影響其他兩層。檢查的內容也只限于數據的形式和取值的范圍,不包括有關業務本身的處理邏輯。
功能層相當于應用的本體,它是將具體的業務處理邏輯編入程序中。而處理所需的數據則要從表示層或數據層取得。表示層和功能層之間的數據交往要盡可能簡潔。數據層就是數據庫管理系統,負責管理對數據庫數據的讀寫。數據庫管理系統必須能迅速執行大量數據的更新和檢索。因此,一般從功能層傳送到數據層的要求大都使用 SQL 語言。
三層 C/S 的解決方案是:對這三層進行明確分割,并在邏輯上使其獨立。原來的數據層作為數據庫管理系統已經獨立出來,所以,關鍵是要將表示層和功能層分離成各自獨立的程序,并且還要使這兩層間的接口簡潔明了。
一般情況是只將表示層配置在客戶機中,如果將功能層也放在客戶機中,與二層 C/S 結構相比,其程序的可維護性要好得多,但是其他問題并未得到解決。客戶機的負荷太重,其業務處理所需的數據要從服務器傳給客戶機,所以系統的性能容易變差。
如果將功能層和數據層分別放在不同的服務器中,則服務器和服務器之間也要進行數據傳送。但是,由于在這種形態中三層是分別放在各自不同的硬件系統上的,所以靈活性很高,能夠適應客戶機數目的增加和處理負荷的變動。例如,在追加新業務處理時,可以相應增加裝載功能層的服務器。因此,系統規模越大這種形態的優點就越顯著。
9.4.2 B/S 架構風格
在三層 C/S 架構中,表示層負責處理用戶的輸入和向客戶的輸出(出于效率的考慮,它可能在向上傳輸用戶的輸入前進行合法性驗證)。功能層負責建立數據庫的連接,根據用戶的請求生成訪問數據庫的 SQL 語句,并把結果返回給客戶端。數據層負責實際的數據庫存儲和檢索,響應功能層的數據處理請求,并將結果返回給功能層。
瀏覽器/服務器(Browser/Server,簡稱 B/S)風格就是上述三層應用結構的一種實現方式,其具體結構為:瀏覽器/Web 服務器/數據庫服務器。采用 B/S 結構的計算機應用系統的基本框架如圖 9-10 所示。
B/S 架構主要是利用不斷成熟的 WWW 瀏覽器技術,結合瀏覽器的多種腳本語言,用通用瀏覽器就實現了原來需要復雜的專用軟件才能實現的強大功能,并節約了開發成本。從某種程度上來說,B/S 結構是一種全新的軟件架構。
在 B/S 結構中,除了數據庫服務器外,應用程序以網頁形式存放于 Web 服務器上,用戶運行某個應用程序時只需在客戶端上的瀏覽器中鍵入相應的網址,調用 Web 服務器上的應用程序并對數據庫進行操作完成相應的數據處理工作,最后將結果通過瀏覽器顯示給用戶。可以說,在 B/S 模式的計算機應用系統中,應用(程序)在一定程度上具有集中特征。
基于 B/S 架構的軟件,系統安裝、修改和維護全在服務器端解決。用戶在使用系統時,僅需要一個瀏覽器就可運行全部的模塊,真正達到了“零客戶端”的功能,很容易在運行時自動升級。B/S 架構還提供了異種機、異種網、異種應用服務的聯機、聯網、統一服務的最現實的開放性基礎。
B/S 結構出現之前,管理信息系統的功能覆蓋范圍主要是組織內部。B/S 結構的“零客戶端”方式,使組織的供應商和客戶(這些供應商和客戶有可能是潛在的,也就是說可能是事先未知的!)的計算機方便地成為管理信息系統的客戶端,進而在限定的功能范圍內查詢組織相關信息,完成與組織的各種業務往來的數據交換和處理工作,擴大了組織計算機應用系統的功能覆蓋范圍,可以更加充分利用網絡上的各種資源,同時應用程序維護的工作量也大大減少。
另外,B/S 結構的計算機應用系統與 Internet 的結合也使新近提出的一些新的
企業計算機應用(如電子商務,客戶關系管理)的實現成為可能。與 C/S 架構相比,B/S 架構也有許多不足之處,例如:
(1)B/S 架構缺乏對動態頁面的支持能力,沒有集成有效的數據庫處理功能。
(2)采用 B/S 架構的應用系統,在數據查詢等響應速度上,要遠遠地低于 C/S 架構。
(3)B/S 架構的數據提交一般以頁面為單位,數據的動態交互性不強,不利于在線事務處理(OnLine Transaction Processing,簡稱 OLTP)應用。
9.4.3 MVC 架構風格
MVC 全名是 Model ViewController,是模型(model)-視圖(view)-控制器(controller)的縮寫,它是分層架構風格的一種。MVC 是由挪威的計算機專家 Trygve M.H. Reenskau 于 1979年提出的軟件架構模式,MVC 最初用于 SmallTalk。MVC 提出的基本思想是進行關注點分離。一個典型的人機交互應用具有三個主要的關注點:數據在可視化界面上的呈現、UI 處理邏輯和業務邏輯。如果按傳統的自治視圖模式(即將與 UI 相關的邏輯都定義在針對視圖
的相關元素的事件上),將三者混合在一起,勢必會帶來一系列問題:
(1)業務邏輯是與 UI 無關的,應該最大限度地被重用。由于業務邏輯定義在自治視圖中,相當于完全與視圖本身綁定在一定,如果我們能夠將 UI 的行為抽象出來,基于抽象化 UI 的處理邏輯也是可以被共享的。但是定義在自治視頻中的 UI 處理邏輯完全喪失了重用的可能。
(2)業務邏輯具有最強的穩定性,UI 處理邏輯次之,而可視化界面上的呈現最差(比如我們經常會為了更好地呈現效果來調整 HTML)。如果將具有不同穩定性的元素融為一體,那么具有最差穩定性的元素決定了整體的穩定性。
(3)任何涉及 UI 的組件都不易測試。UI 是呈現給人看的,并且用于人機交互,用機器來模擬活生生的人來對組件實施自動化測試不是一件容易的事,自治視圖嚴重損害了組件的可測試性。 正是為了解決以上的問題,所以我們需要采用關注點分離的方針來將可視化界面呈現、UI 處理邏輯和業務邏輯三者分離出來,并且采用合理的交互方式將它們之間的依賴降到最低。
MVC 中各個部分的分工與協作是這樣的:
(1)Model 是對應用狀態和業務功能的封裝,我們可以將它理解為同時包含數據和行為的領域模型。Model 接受 Controller 的請求并完成相應的業務處理,在狀態改變的時候向 View 發出相應的通知。
(2)View 實現可視化界面的呈現并捕捉最終用戶的交互操作(例如鼠標和鍵盤的操作)。
(3)View 捕獲到用戶交互操作后會直接轉發給 Controller,后者完成相應的 UI 邏輯。如果需要涉及業務功能的調用,Controller 會直接調用 Model。在完成 UI 處理后,Controller 會根據需要控制原 View 或者創建新的 View 對用戶交互操作予以響應。
MVC 模式的基本結構如圖 9-11 所示。
9.4.4 MVP 架構風格
MVP 的全稱為 Model-View-Presenter,Model 提供數據,View 負責顯示,Controller/ Presenter 負責邏輯的處理。MVP 是從經典的模式 MVC 演變而來,它們的基本思想有相通的地方:Controller/Presenter 負責邏輯的處理,Model 提供數據,View 負責顯示。
當然 MVP 與 MVC 也有一些顯著的區別,MVC 模式中元素之間“混亂”的交互主要體現在允許 View 和 Model 直接進行“交流”,這在 MVP 模式中是不允許的。在 MVP 中 View 并不直接使用 Model,它們之間的通信是通過 Presenter (MVC 中的 Controller)來進行的,所有的交互都發生在 Presenter 內部,而在 MVC 中 View 會直接從 Model 中讀取數據而不是通
過 Controller。
MVP 不僅僅避免了 View 和 Model 之間的耦合,還進一步降低了 Presenter 對 View 的依賴。Presenter 依賴的是一個抽象化的 View,即 View 實現的接口 IView,這帶來的最直接的好處,就是使定義在 Presenter 中的 UI 處理邏輯變得易于測試。由于 Presenter 對View 的依賴行為定義在接口 IView 中,我們只需要一個實現了這個接口的 View 就能對Presenter 進行測試。MVP 的結構如圖 9-12 所示。
下面我們來分析 MVP 的優缺點。MVP 的優點包括:
(1)模型與視圖完全分離,我們可以修改視圖而不影響模型。
(2)可以更高效地使用模型,因為所有的交互都發生在一個地方—Presenter 內部。
(3)我們可以將一個 Presenter 用于多個視圖,而不需要改變 Presenter 的邏輯。這個特性非常的有用,因為視圖的變化總是比模型的變化頻繁。
(4)如果我們把邏輯放在 Presenter 中,那么我們就可以脫離用戶接口來測試這些邏輯(單元測試)。
MVP 的缺點包括:
由于對視圖的渲染放在了 Presenter 中,所以視圖和 Presenter 的交互會過于頻繁。還有一點需要明白,如果 Presenter 過多地渲染了視圖,往往會使得它與特定的視圖的聯系過于緊密。一旦視圖需要變更,那么 Presenter 也需要變更了。比如說,原本用來呈現 HTML 的 Presenter 現在也需要用于呈現 PDF 了,那么視圖很有可能也需要變更。
9.5 面向服務的架構
迄今為止,對于面向服務的架構(Service-Oriented Architecture,SOA)還沒有一個公認的定義。許多組織從不同的角度和不同的側面對 SOA 進行了描述,較為典型的有以下三個:
(1)W3C 的定義:SOA 是一種應用程序架構,在這種架構中,所有功能都定義為獨立的服務,這些服務帶有定義明確的可調用接口,能夠以定義好的順序調用這些服務來形成業務流程。
(2)Service-architecture.com 的定義:服務是精確定義、封裝完善、獨立于其他服務所處環境和狀態的函數。SOA 本質上是服務的集合,服務之間彼此通信,這種通信可能是簡單的數據傳送,也可能是兩個或更多的服務協調進行某些活動。服務之間需要某些方法進行連接。
(3)Gartner 的定義:SOA 是一種 C/S 架構的軟件設計方法,應用由服務和服務使用者組成,SOA 與大多數通用的 C/S 架構模型不同之處,在于它著重強調構件的松散耦合,并使用獨立的標準接口。
9.5.1 SOA 概述
SOA 是一種在計算環境中設計、開發、部署和管理離散邏輯單元(服務)模型的方法。
SOA 并不是一個新鮮事物,而只是面向對象模型的一種替代。雖然基于 SOA 的系統并不排除使用 OOD 來構建單個服務,但是其整體設計卻是面向服務的。由于 SOA 考慮到了系統內的對象,所以雖然 SOA 是基于對象的,但是作為一個整體,它卻不是面向對象的。
SOA 系統原型的一個典型例子是 CORBA,它已經出現很長時間,其定義的概念與 SOA 相似。SOA 建立在 XML 等新技術的基礎上,通過使用基于 XML 的語言來描述接口,服務已經轉到更動態且更靈活的接口系統中,CORBA 中的 IDL 無法與之相比。圖 9-13 描述了一個完整的 SOA 模型。
在 SOA 模型中,所有的功能都定義成了獨立的服務。服務之間通過交互和協調完成業務的整體邏輯。所有的服務通過服務總線或流程管理器來連接。這種松散耦合的架構使得各服務在交互過程中無需考慮雙方的內部實現細節,以及部署在什么平臺上。
- 服務的基本結構
一個獨立的服務基本結構如圖 9-14 所示。
由圖 9-14 可以看出,服務模型的表示層從邏輯層分離出來,中間增加了服務對外的接口層。通過服務接口的標準化描述,使得服務可以提供給在任何異構平臺和任何用戶接口使用。這允許并支持基于服務的系統成為松散耦合、面向構件和跨技術實現,服務請求者很可能根本不知道服務在哪里運行、是由哪種語言編寫的,以及消息的傳輸路徑,而是只需要提出服務請求,然后就會得到答案。
2.SOA 設計原則
在 SOA 架構中,繼承了來自對象和構件設計的各種原則,例如,封裝和自我包含等。那些保證服務的靈活性、松散耦合和復用能力的設計原則,對 SOA 架構來說同樣是非常重要的。關于服務,一些常見的設計原則如下:
(1)明確定義的接口。服務請求者依賴于服務規約來調用服務,因此,服務定義必須長時間穩定,一旦公布,不能隨意更改;服務的定義應盡可能明確,減少請求者的不適當使用;不要讓請求者看到服務內部的私有數據。
(2)自包含和模塊化。服務封裝了那些在業務上穩定、重復出現的活動和構件,實現服務的功能實體是完全獨立自主的,獨立進行部署、版本控制、自我管理和恢復。
(3)粗粒度。服務數量不應該太多,依靠消息交互而不是遠程過程調用,通常消息量比較大,但是服務之間的交互頻度較低。
(4)松耦合。服務請求者可見的是服務的接口,其位置、實現技術、當前狀態和私有數據等,對服務請求者而言是不可見的。
(5)互操作性、兼容和策略聲明。為了確保服務規約的全面和明確,策略成為一個越來越重要的方面。這可以是技術相關的內容,例如,一個服務對安全性方面的要求;也可以是與業務有關的語義方面的內容,例如,需要滿足的費用或者服務級別方面的要求,這些策略對于服務在交互時是非常重要的。
- 服務構件與傳統構件
服務構件架構(Service Component Architecture,SCA)是基于 SOA 的思想描述服務之間組合和協作的規范,它描述用于使用 SOA 構建應用程序和系統的模型。它可簡化使用SOA 進行的應用程序開發和實現工作。SCA 提供了構建粗粒度構件的機制,這些粗粒度構件由細粒度構件組裝而成。SCA 將傳統中間件編程從業務邏輯分離出來,從而使程序員免受其復雜性的困擾。它允許開發人員集中精力編寫業務邏輯,而不必將大量的時間花費在更為底層的技術實現上。
SCA 服務構件與傳統構件的主要區別在于,服務構件往往是粗粒度的,而傳統構件以細粒度居多;服務構件的接口是標準的,主要是服務描述語言接口,而傳統構件常以具體 API 形式出現;服務構件的實現與語言是無關的,而傳統構件常綁定某種特定的語言;服務構件可以通過構件容器提供 QoS 的服務,而傳統構件完全由程序代碼直接控制。
9.5.2 SOA 的關鍵技術
SOA 伴隨著無處不在的標準,為企業的現有資產或投資帶來了更好的復用性。SOA 能夠在最新的和現有的系統之上創建應用,借助現有的應用產生新的服務,為企業提供更好的靈活性來構建系統和業務流程。SOA 是一種全新的架構,為了支持其各種特性,相關的技術規范不斷推出。與 SOA 緊密相關的技術主要有 UDDI、WSDL、SOAP 和 REST 等,而這些技術都是以 XML 為基礎而發展起來的。
- UDDI
UDDI(Universal DescriptionDiscovery and Integration,統一描述、發現和集成)提供了一種服務發布、查找和定位的方法,是服務的信息注冊規范,以便被需要該服務的用戶發現和使用它。UDDI 規范描述了服務的概念,同時也定義了一種編程接口。通過 UDDI 提供的標準接口,企業可以發布自己的服務供其他企業查詢和調用,也可以查詢特定服務的描述信息,并動態綁定到該服務上。
在 UDDI 技術規范中,主要包含以下三個部分的內容:
(1)數據模型。UDDI 數據模型是一個用于描述業務組織和服務的 XML Schema。
(2)API。UDDI API 是一組用于查找或發布 UDDI 數據的方法,UDDI API 基于 SOAP。
(3)注冊服務。UDDI 注冊服務是 SOA 中的一種基礎設施,對應著服務注冊中心的角色。
2.WSDL
WSDL(Web ServiceDescription Language,Web 服務描述語言)是對服務進行描述的語言,它有一套基于 XML 的語法定義。WSDL 描述的重點是服務,它包含服務實現定義和服務接口定義,如圖 9-15 所示。
采用抽象接口定義對于提高系統的擴展性很有幫助。服務接口定義就是一種抽象的、可重用的定義,行業標準組織可以使用這種抽象的定義來規定一些標準的服務類型,服務實現者可以根據這些標準定義來實現具體的服務。
服務實現定義描述了給定服務提供者如何實現特定的服務接口。服務實現定義中包含服務和端口描述。一個服務往往會包含多個服務訪問入口,而每個訪問入口都會使用一個端口元素來描述,端口描述的是一個服務訪問入口的部署細節,例如,通過哪個地址來訪問,應當使用怎樣的消息調用模式來訪問等。
3.SOAP
SOAP(Simple ObjectAccess Protocol,簡單對象訪問協議)定義了服務請求者和服務提供者之間的消息傳輸規范。SOAP 用 XML 來格式化消息,用 HTTP 來承載消息。通過 SOAP,應用程序可以在網絡中進行數據交換和遠程過程調用(Remote Procedure Call, RPC)。SOAP 主要包括以下四個部分:
(1)封裝。SOAP 封裝定義了一個整體框架,用來表示消息中包含什么內容,誰來處理這些內容,以及這些內容是可選的還是必需的。
(2)編碼規則。SOAP 編碼規則定義了一種序列化的機制,用于交換系統所定義的數據類型的實例。
(3)RPC 表示。SOAP RPC 表示定義了一個用來表示遠程過程調用和應答的協議。
(4)綁定。SOAP 綁定定義了一個使用底層傳輸協議來完成在節點之間交換 SOAP 封裝的約定。
SOAP 消息基本上是從發送端到接收端的單向傳輸,但它們常常結合起來執行類似于請求/應答的模式。所有的 SOAP 消息都使用 XML 進行編碼。SOAP 消息包括以下三個部分:
(1)封裝(信封)。封裝的元素名是 Envelope,在表示消息的 XML 文檔中,封裝是頂層元素,在 SOAP 消息中必須出現。
(2)SOAP 頭。SOAP 頭的元素名是 Header,提供了向 SOAP 消息中添加關于這條SOAP 消息的某些要素的機制。SOAP 定義了少量的屬性用來表明這項要素是否可選以及由誰來處理。SOAP 頭在 SOAP 消息中可能出現,也可能不出現。如果出現的話,必須是 SOAP 封裝元素的第一個直接子元素。
(3)SOAP 體。SOAP 體的元素名是 Body,是包含消息的最終接收者想要的信息的容器。SOAP 體在 SOAP 消息中必須出現且必須是 SOAP 封裝元素的直接子元素。如果有頭元素,則 SOAP 體必須直接跟在 SOAP 頭元素之后;如果沒有頭元素,則 SOAP 體必須是SOAP 封裝元素的第一個直接子元素。
4.REST
REST(RepresentationalState Transfer,表述性狀態轉移)是一種只使用 HTTP 和 XML 進行基于 Web 通信的技術,可以降低開發的復雜性,提高系統的可伸縮性。它的簡單性和缺少嚴格配置文件的特性,使它與 SOAP 很好地隔離開來,REST 從根本上來說只支持幾個操作(POST、GET、PUT 和 DELETE),這些操作適用于所有的消息。REST 提出了如下一些設計概念和準則:
(1)網絡上的所有事物都被抽象為資源。
(2)每個資源對應一個唯一的資源標識。
(3)通過通用的連接件接口對資源進行操作。
(4)對資源的各種操作不會改變資源標識。
(5)所有的操作都是無狀態的。
9.5.3 SOA 的實現方法
SOA 只是一種概念和思想,需要借助于具體的技術和方法來實現它。從本質上來看,SOA 是用本地計算模型來實現一個分布式的計算應用,也有人稱這種方法為“本地化設計,分布式工作”模型。CORBA、DCOM 和 EJB 等都屬于這種解決方式,也就是說,SOA 最終可以基于這些標準來實現。
從邏輯上和高層抽象來看,目前,實現 SOA 的方法也比較多,其中主流方式有 Web Service、企業服務總線和服務注冊表。
1.Web Service
在 Web Service(Web 服務)的解決方案中,一共有三種工作角色,其中服務提供者和服務請求者是必需的,服務注冊中心是一個可選的角色。它們之間的交互和操作構成了 SOA 的一種實現架構,如圖 9-16 所示。
(1)服務提供者。服務提供者是服務的所有者,該角色負責定義并實現服務,使用 WSDL 對服務進行詳細、準確、規范地描述,并將該描述發布到服務注冊中心,供服務請求者查找并綁定使用。
(2)服務請求者。服務請求者是服務的使用者,雖然服務面向的是程序,但程序的最終使用者仍然是用戶。從架構的角度看,服務請求者是查找、綁定并調用服務,或與服務進行交互的應用程序。服務請求者角色可以由瀏覽器來擔當,由人或程序(例如,另外一個服務)來控制。
(3)服務注冊中心。服務注冊中心是連接服務提供者和服務請求者的紐帶,服務提供者在此發布他們的服務描述,而服務請求者在服務注冊中心查找他們需要的服務。不過,在某些情況下,服務注冊中心是整個模型中的可選角色。例如,如果使用靜態綁定的服務,服務提供者則可以把描述直接發送給服務請求者。
Web Service 模型中的操作包括發布、查找和綁定,這些操作可以單次或反復出現。
(1)發布。為了使用戶能夠訪問服務,服務提供者需要發布服務描述,以便服務請求者可以查找它。
(2)查找。在查找操作中,服務請求者直接檢索服務描述或在服務注冊中心查詢所要求的服務類型。對服務請求者而言,可能會在生命周期的兩個不同階段中涉及查找操作,首先是在設計階段,為了程序開發而查找服務的接口描述;其次是在運行階段,為了調用而查找服務的位置描述。
(3)綁定。在綁定操作中,服務請求者使用服務描述中的綁定細節來定位、聯系并調用服務,從而在運行時與服務進行交互。綁定可以分為動態綁定和靜態綁定。在動態綁定中,服務請求者通過服務注冊中心查找服務描述,并動態地與服務交互;在靜態綁定中,服務請求者已經與服務提供者達成默契,通過本地文件或其他方式直接與服務進行綁定。
在采用 Web Service 作為 SOA 的實現技術時,應用系統大致可以分為六個層次,分別是底層傳輸層、服務通信協議層、服務描述層、 服務層、業務流程層和服務注冊層。
(1)底層傳輸層。底層傳輸層主要負責消息的傳輸機制,HTTP、JMS(Java Messaging Service,Java 消息服務)和 SMTP 都可以作為服務的消息傳輸協議,其中 HTTP 使用最廣。
(2)服務通信協議層。服務通信協議層的主要功能是描述并定義服務之間進行消息傳遞所需的技術標準,常用的標準是 SOAP 和 REST 協議。
(3)服務描述層。服務描述層主要以一種統一的方式描述服務的接口與消息交換方式,相關的標準是 WSDL。
(4)服務層。服務層的主要功能是將遺留系統進行包裝,并通過發布的 WSDL 接口描述被定位和調用。
(5)業務流程層。業務流程層的主要功能是支持服務發現,服務調用和點到點的服務調用,并將業務流程從服務的底層調用抽象出來。
(6)服務注冊層的主要功能是使服務提供者能夠通過 WSDL 發布服務定義,并支持服務請求者查找所需的服務信息。相關的標準是 UDDI。
- 服務注冊表
服務注冊表(service registry)雖然也具有運行時的功能,但主要在 SOA 設計時使用。它提供一個策略執行點(Policy Enforcement Point,PEP),在這個點上,服務可以在 SOA 中注冊,從而可以被發現和使用。服務注冊表可以包括有關服務和相關構件的配置、依從性和約束文件。從理論上來說,任何幫助服務注冊、發現和查找服務合約、元數據和策略的信息庫、數據庫、目錄或其他節點都可以被認為是一個注冊表。大多數商用服務注冊產品支持服務注冊、服務位置和服務綁定功能。
(1)服務注冊。服務注冊是指服務提供者向服務注冊表發布服務的功能(服務合約),包括服務身份、位置、方法、綁定、配置、方案和策略等描述性屬性。使用服務注冊表實現SOA 時,要限制哪些新服務可以向注冊表發布、由誰發布以及誰批準和根據什么條件批準等,以便使服務能夠有序的注冊。
(2)服務位置。服務位置是指服務使用者,幫助它們查詢已注冊的服務,尋找符合自身要求的服務。這種查找主要是通過檢索服務合約來實現的,在使用服務注冊表實現 SOA 時,需要規定哪些用戶可以訪問服務注冊表,以及哪些服務屬性可以通過服務注冊表進行暴露等,以便服務能得到有效的、經過授權的使用。
(3)服務綁定。服務使用者利用查找到的服務合約來開發代碼,開發的代碼將與注冊的服務進行綁定,調用注冊的服務,以及與它們實現互動。可以利用集成的開發環境自動將新開發的服務與不同的新協議、方案和程序間通信所需的其他接口綁定在一起。
- 企業服務總線
ESB 的概念是從 SOA 發展而來的,它是一種為進行連接服務提供的標準化的通信基礎結構,基于開放的標準,為應用提供了一個可靠的、可度量的和高度安全的環境,并可幫助企業對業務流程進行設計和模擬,對每個業務流程實施控制和跟蹤、分析并改進流程和性能。
在一個復雜的企業計算環境中,如果服務提供者和服務請求者之間采用直接的端到端的交互,那么隨著企業信息系統的增加和復雜度的提高,系統之間的關聯會逐漸變得非常復雜,形成一個網狀結構,這將帶來昂貴的系統維護費用,同時也使得 IT 基礎設施的復用變得困難重重。ESB 提供了一種基礎設施,消除了服務請求者與服務提供者之間的直接連接,使得服務請求者與服務提供者之間進一步解耦。
ESB 是由中間件技術實現并支持 SOA 的一組基礎架構,是傳統中間件技術與 XML、Web Service 等技術結合的產物,是在整個企業集成架構下的面向服務的企業應用集成機制。具體來說,ESB 具有以下功能:
(1)支持異構環境中的服務、消息和基于事件的交互,并且具有適當的服務級別和可管理性。
(2)通過使用 ESB,可以在幾乎不更改代碼的情況下,以一種無縫的非侵入方式使現有系統具有全新的服務接口,并能夠在部署環境中支持任何標準。
(3)充當緩沖器的 ESB(負責在諸多服務之間轉換業務邏輯和數據格式)與服務邏輯相分離,從而使不同的系統可以同時使用同一個服務,不用在系統或數據發生變化時,改動服務代碼。
(4)在更高的層次,ESB 還提供諸如服務代理和協議轉換等功能。允許在多種形式下通過像 HTTP、SOAP 和 JMS 總線的多種傳輸方式,主要是以網絡服務的形式,為發表、注冊、發現和使用企業服務或界面提供基礎設施。
(5)提供可配置的消息轉換翻譯機制和基于消息內容的消息路由服務,傳輸消息到不同的目的地。
(6)提供安全和擁有者機制,以保證消息和服務使用的認證、授權和完整性。
在企業應用集成方面,與現存的、專有的集成解決方案相比,ESB 具有以下優勢:
(1)擴展的、基于標準的連接。ESB 形成一個基于標準的信息骨架,使得在系統內部和整個價值鏈中可以容易地進行異步或同步數據交換。ESB 通過使用 XML、SOAP 和其他標準,提供了更強大的系統連接性。
(2)靈活的、服務導向的應用組合。基于 SOA,ESB 使復雜的分布式系統(包括跨多個應用、系統和防火墻的集成方案)能夠由以前開發測試過的服務組合而成,使系統具有高度可擴展性。
(3)提高復用率,降低成本。按照 SOA 方法構建應用,提高了復用率,簡化了維護工作,進而減少了系統總體成本。
(4)減少市場反應時間,提高生產率。ESB 通過構件和服務復用,按照 SOA 的思想簡化應用組合,基于標準的通信、轉換和連接來實現這些優點。
9.5.4 微服務
微服務顧名思義,就是很小的服務,所以它屬于面向服務架構的一種。通俗一點來說,微服務類似于古代著名的發明,活字印刷術,每個服務都是一個組件,通過編排組合的方式來使用,從而真正做到了獨立、解耦、組件化、易維護、可復用、可替換、高可用、最終達到提高交付質量、縮短交付周期的效果。
從專業的角度來看,微服務架構是一種架構模式,它提倡將單一應用程序劃分成一組小的服務,服務之間互相協調、互相配合,為用戶提供最終價值。每個服務運行在其獨立的進程中,服務與服務間采用輕量級的通信機制互相溝通(通常是基于 HTTP 協議的 RESTful API)。每個服務都圍繞著具體業務進行構建,并且能夠被獨立的部署到生產環境、類生產環境等。另外,應當盡量避免統一的、集中式的服務管理機制,對具體的一個服務而言,應根據業務上下文,選擇合適的語言、工具對其進行構建。
所以總結起來,微服務的核心特點為:小, 且專注于做?件事情、輕量級的通信機制、松耦合、獨立部署。
1.微服務的優勢
微服務之所以能盛行,必然是有它獨特優勢的,下面我們來分析微服務有哪些方面的優勢。
(1)技術異構性
在微服務架構中,每個服務都是一個相對獨立的個體,每個服務都可以選擇適合于自身的技術來實現。如,要開發一個社交平臺,此時,我們可能使用文檔型數據庫來存儲帖 子的內容,使用圖數據來存儲朋友圈的這些關系等,這樣可以把每一塊的性能都充分發揮 出來。
同時,在應用新技術時,微服務架構也提供了更好的試驗場。因為對于單塊的系統而 言,采用一個新的語言、數據庫或者框架都會對整個系統產生巨大的影響,這樣導致我們 想嘗試新技術時,望而卻步。但微服務不同,我們完全可以只在一個微服務中采用新技術, 待技術使用熟練之后,再推廣到其他服務。
(2)彈性
彈性主要講的是系統中一部分出現故障會引起多大問題。在單塊系統中,一個部分出現問題,可能導致整體系統的問題。而微服務架構中,每個服務可以內置可用性的解決方 案與功能降級方案,所以比單塊系統強。
(3)擴展
單塊系統中,我們要做擴展,往往是整體進行擴展。而在微服務架構中,可以針對單個服務進行擴展。
(4)簡化部署
在大型單塊系統中,即使修改一行代碼,也需要重新部署整個應用系統。這種部署的影響很大、風險很高,因此不敢輕易地重新部署。而微服務架構中,每個服務的部署都是 獨立的,這樣就可以更快地對特定部分的代碼進行部署。
(5)與結織結構相匹配
我們都知道,團隊越大越難管理,同時團隊越大也代表系統規模越大代碼庫越大,這樣容易引起一系列的問題。且當團隊是分布式的時候,問題更嚴重。微服務架構就能很好地解決這個問題,微服務架構可以將架構與組織結構相匹配,避免出現過大的代碼庫,從而獲得理想的團隊大小及生產力。服務的所有權也可以在團隊之 間遷移,從而避免異地團隊的出現。
(6)可組合性
在微服務架構中,系統會開放很多接口供外部使用。當情況發生改變時,可以使用不同的方式構建應用,而整體化應用程序只能提供一個非常粗粒度的接口供外部使用。
(7)對可替代性的優化
在單塊系統中如果刪除系統中的上百行代碼,也許不知道會發生什么,引起什么樣的問題,因為單塊系統中關聯性很強。但在微服務架構中,我們可以在需要時輕易地重寫服務,或者刪除不再使用的服務。
- 微服務面臨的挑戰
軟件開發業內有一句名言“軟件開發沒有銀彈”,雖然前面介紹了微服務很多方面的優勢,但微服務并不能解決所有問題。下面我們來分析在使用微服務架構時可能面臨的一些挑戰。
(1)分布式系統的復雜度
使用微服務實現分布式系統的復雜度要比單塊系統高。這表現在多個方面,如:性能方面微服務是拆分成多個服務進行部署,服務間的通信都是通過網絡,此時的性能會受影響。同時可靠性也會受影響。數據一致性也需要嚴格控制,其成本也比單塊系統高。
(2)運維成本
相比傳統的單塊架構應用,微服務將系統分成多個獨立的部分,每個部分都是可以獨立部署的業務單元。這就意味著,原來適用于單塊架構的集中式的部署、配置、監控或者日志收集等方式,在微服務架構下,隨著服務數量的增多,每個服務都需要獨立的配置、部署、監控、日志收集等,因此成本呈指數級增長。
(3)部署自動化
傳統單塊系統部署往往是以月、周為單位,部署頻度很低,在這種情況下,手動部署是可以滿足需求的。而對于微服務架構而言,每個服務都是一個獨立可部署的業務單元,每個服務的修改都需要獨立部署。這樣部署的成本是比較高的,如亞馬遜,每天都要執行數十次、甚至上百次的部署,此時仍用人工部署是行不通的,要使用自動化部署。如何有效地構建自動化部署流水線,降低部署成本、提高部署頻率,是微服務架構下需要面臨的一個挑戰。
(4)DevOps 與組織結構
傳統單塊架構中,團隊通常是按技能劃分,如開發部、測試部、運維部,并通過項目的方式協作,完成系統交付。而在微服務架構的實施過程中,除了如上所述的交付、運維上存在的挑戰,在組織或者團隊層面,如何傳遞DevOps 文化的價值,讓團隊理解 DevOps 文化的價值,并構建全功能團隊,也是一個不小的挑戰。微服務不僅表現出一種架構模型,同樣也表現出一種組織模型。這種新型的組織模型意味著開發人員和運維的角色發生了變化,開發者將承擔起服務整個生命周期的責任,包括部署和監控,而運維也越來越多地表現出一種顧問式的角色,盡早考慮服務如何部署。因此,如何在微服務的實施中,按需調整組織架構,構建全功能的團隊,是一個不小的挑戰。
(5)服務間依賴測試
由于微服務架構是把系統拆分為若干個可獨立部署的服務,所以需要進行服務間的依賴測試。在服務數量較多的情況下,如何有效地保證服務之間能有效按照接口的約定正常工作,成為微服務實施過程中必須面臨的巨大挑戰。
(6)服務間依賴管理
傳統的單塊系統,功能實現比較集中,大部分功能都運行在同一個應用中,同其他系統依賴較少。而微服務架構則不同,在將系統功能拆分成相互協作的獨立服務之后,隨著微服務個數的增多,如何清晰有效地展示服務之間的依賴關系,成為了一個挑戰。
3.微服務與 SOA
微服務可以講是 SOA 的一種,但仔細分析與推敲,我們又能發現他們的一些差異。這種差異表現在多個方面,具體如表 9-8 所示。
這些差異自然影響到其實現,在實現方面的主要差異如表 9-9 所示