走向.NET架構設計-第六章-服務層設計(中篇)
前言:上一篇文章介紹了一些服務層的基本知識,而且也簡要的介紹了SOA的有關知識,本篇主要是介紹在服務層可以採用的一些模式。
本篇議題如下:
Façade 模式
Document Message和Request-Reponse模式
Reservation 模式
Idempotent模式
Façade設計模式
在SOA用戶端的設計中,最常用的模式就是Façade模式了。Façade模式簡化了複雜子系統的調用介面,也就說,Façade隱藏了子系統之間的複雜關係,給用戶端一個簡單的調用介面。
Façade模式的好處如下:
1. 它可以使得第三方的類庫經過封裝之後,通過一個簡單的介面就可以調用,如所示。
2. 它可以通過抽象等方式來解耦其他系統之間的依賴。
3. 它可以使得各個子系統之間的調用複雜度隱藏,通過一個簡單的介面就可以調用,如所示
在上面的圖中:
1. 用戶端調用Façade的一個簡單的API來執行一個任務。用戶端不知道Façade內部是如何?的,可能只一個任務的執行涉及到很多內部子系統的互動和合作。
2. SubSystemA和SubSystemB才是真正的任務執行者。
下面我們就來看看用戶端和服務層之間進行通訊的一些模式。
註:把這些模式講完之後就講一個如何使用這些模式的例子。
Document Message和Request-Reponse模式(“文檔訊息模式”和”請求-響應模式”)
在體會”文檔訊息模式”的好處之前,我們先來看看一種通訊方式:RPC(Remote Procedure Call 遠端程序呼叫):RPC方式通過暴露很多不同參數的API來實現提供不同服務,如下:
Customer[] RetrieveCustomers(string country);
Customer[] RetrieveCustomers (string country, string postalCode);
Customer[] RetrieveCustomers (string country, string postalCode, string street);
上面的服務介面允許用戶端通過三種方式來擷取使用者的資訊:通過提供不同的參數來實現。這種方式的維護很難的,而且往往把用戶端搞糊塗,而且伺服器端可能最後向用戶端暴露很多名字一樣的方法,儘管可以在WCF中改變方法最後顯示到用戶端的名字,但是方法依然泛濫。
“文檔訊息模式”可以讓用戶端以統一和靈活的方式和服務進行通訊。“文檔訊息模式”把用戶端把所有的請求的資訊封裝成為一個資訊體,發送給服務端,而且服務端的介面的定義也非常的簡單,如下:
Customer[] FindBy(CustomerSearchRequest request);
這個訊息體的定義如下:
public class CustomerSearchRequest
{
public string Country { get; set; }
public string PostalCode { get; set; }
public string Street { get; set; }
}
有的時候訊息體還攜帶其他額外的資訊到服務端,如服務的版本號碼,驗證授權標識等。當然了,這些額外的,相同的資訊,我們可以定義一個請求訊息的基本,然後讓所有的請求訊息都整合基類。
通過使用”文檔訊息模式”,我們就解決了之前RPC的一些問題,當然服務端對訊息要做一些處理的。
”文檔訊息模式”一般和”要求-回應模式”一起使用。如之前的例子,我們是直接返回了Customer的數組,其實有些時候可能不想把業務類的定義暴露出來,而且可能我們還要給用戶端返回添加額外的資訊,那麼我們的服務端的介面定義如下:
CustomerSearchResponse RetrieveCustomers(CustomerSearchRequest request);
其實在之前的一些章節中的代碼的例子,很多都示範了這樣的模式的使用。
大家可以看看一般”文檔訊息模式”和”要求-回應模式”的圖示:
Reservation 模式(預約保留模式)
一般情況下,SOA中伺服器那邊都是無狀態的,但是可能有些時候,我們需要伺服器端來儲存一個長時間啟動並執行服務的一些狀態,在這段時間內,用戶端可能向伺服器端發送很多的請求都被當成一個事務或者一個工作單元來處理。
Reservation模式就是來解決這樣的問題的:
1. 我們可以發送一個請求給伺服器,從服務端響應中擷取一個預約的唯一編號
2. 用戶端餘下的請求中都帶上這個編號,以便伺服器那邊可以把這些請求當做一個交易處理來完成。
通常情況下,這個預約的編號是有一定的期限的,也就說,一段時間之後,這個編號在服務端那邊就到期了,主要是為了避免資源的耗費以及一些安全問題。
我們還是看看下面的一個線上訂票系統中使用“Reservation 模式”的圖示:
在中:
1. 用戶端首先調用ReserveTickets服務方法,並且提供一些基本的資訊給伺服器:訂閱2張票等。
2. 服務端的響應就返回了一個預約的Id和一個到期的時間。
3. 用戶端程式執行一個邏輯。這些邏輯可能會從涉及到把擷取customer的詳細資料作為訂票一個處理過程,或者進行更多的複雜的用戶端和服務端的互動。
4. 最後用戶端把服務端需要的資訊連同預約的Id一同提交,調用PurchaseTicket方法,然後服務端就返回訂票成功的編號。
可能上面的例子不是很恰當,大家明白其中的意思就行。
Idempotent模式(等冪模式)
在調用服務介面的時候,可能出現:用同樣的參數來多次調用同一個服務介面,這種情況,但是可能是我們想要的,但是也可以不是我們想要的。例如,在訂單系統中,由於某些原因,導致使用者把同一個賬單提交了多次(如,不小心點了多次提交按鈕),那麼系統中的資料就出問題。所以可以採用Idempotent模式來確保相同的參數提交多次,但是服務端只是處理一次。
Idempotent模式的基本思想是這樣的:每一次的用戶端的請求,都被賦予了一個唯一的請求標識(如,這個標識的建置規則可能是通過這個請求的一些參數做一些演算法來產生)。在服務端就在一個儲存地區檢查這個唯一的標識時候已經被處理過了,是否有對應的響應資訊,如果有,那麼直接把響應資訊返回;如果沒有,那麼處理這個請求。
如所示:
今天就寫到這裡,下一篇就開始利用WCF來做一個Demo了。