SCA(服務元件架構)程式設計模式

Hoking發表於2016-05-22

本文轉自:http://www.ibm.com/developerworks/cn/webservices/ws-sca/

       本文將介紹SCA程式設計模型中的基本概念,並以一個簡單的例子來說明它的一些基本用法,期待能夠拋磚引玉,併為讀者以後深入理解SCA打下基礎。

概覽

       目前業界主要的軟體廠商都在大力推廣面向服務的架構(Service Oritented Architecture,SOA)的概念,但是對於多數客戶來說,SOA的概念還是顯得相對抽象的。為了使客戶能夠更加簡單的實現向這種面向服務架構的轉變,IBM在推出一系列WebSphere新產品的同時,提出了一種新的服務元件模型。這是一種全新的、跟語言無關的程式設計模型,它提供了一種統一的呼叫方法,從而使得客戶可以把不同的元件型別,比如POJO, EJB, 流程元件,人工互動元件等都可以通過一種標準的介面來封裝和呼叫。結合SDO的資料模型,這種服務元件的程式設計模型可以大大的簡化客戶的程式設計,提高應用的靈活性,這就是面向服務元件的架構(Service Component Architecture,SCA)。目前IBM 對SCA的支援是在最近推出的WebSphere Process Server(WPS)中,但是以後該服務元件模型將作為一個IBM軟體重要的程式設計模型被應用到底層平臺當中。本文將介紹SCA程式設計模型中的基本概念,並以一個簡單的例子來說明它的一些基本用法,期待能夠拋磚引玉,併為讀者以後深入瞭解SCA打下基礎。

1.1  SCA的起源

基於元件的程式設計一直是軟體業簡化程式設計和提高效率和質量的一個重要方法,但是往往對於不同語言我們有不同的元件模型,從而需要不同的呼叫方式。比如在J2EE技術領域,我們就有EJB,POJO,JDBC,JMS等,這對於開發人員來說是一個極大的挑戰。為了給這些不同的介面提供一個統一的呼叫方式,IBM提出了WSIF (Web Service Invocation Framework,具體請參考http://ws.apache.org/wsif/ ),並將它貢獻給Apache組織。WSIF作為WebService領域的一個規範,提供了一種基於Java API統一呼叫各種服務的能力。但是WSIF沒有形成一個基於元件的架構模型,因此IBM在此基礎上推出了一個面向服務的元件模型(Service Oritented Architecture, SCA)。這個模型不但解決了統一呼叫的問題,還提出了一個基於元件的構建模型,並提供了許多面向企業計算的QoS能力。因此,從技術的角度來說,SCA是WSIF的延續和擴充套件。SCA的目的是使使用者在構建企業應用時有一個不再直接面對具體的技術細節的層次,而是通過服務元件的方式來構建應用。這種方式也使得客戶的企業應用具有良好的分層架構,能夠很好的分離應用的業務邏輯和IT邏輯,不但易於應用的構建,也易於應用的更改和部署。

1.2  SCA中的基本概念

服務元件模型(SCA)中提出了一些新的概念,比如服務元件,模組,共享庫,匯入和匯出等。下面將分別解釋這些服務元件中的基本概念。

1.2.1服務元件

服務元件是SCA中的基本組成元素和基本構建單位,也是我們具體實現業務邏輯的地方。我們可以把它看成是構建我們應用的積木。我們可以非常容易地把傳統的POJO,無狀態會話BEAN等包裝成SCA中的服務元件。 SCA服務元件的主要介面規範是基於WSDL(Web Service Description Language)的,另外為了給Java程式設計人員提供一個比較直接的介面,SCA的部分服務元件也提供了Java介面。因此,使用服務元件的客戶端可以選擇使用WSDL介面或Java介面。

服務元件提供給別的服務呼叫的入口叫Interface(介面)。而服務元件本身可能也需要呼叫別的服務,這個呼叫出口叫Reference(引用)。無論是介面還是引用,其呼叫規範都是WSDL或Java介面。SCA服務元件的介面模型請參考圖 1:

圖 1:SCA 服務元件介面模型


WebSphere ProcessServer 充分利用了SCA的這種元件架構,並在產品中提供了一些與業務聯絡比較緊密的元件,比如業務流程,人工任務,業務狀態機,業務規則等。這樣使用者就可以直接利用這些服務元件,構建自己的業務流程或其它業務整合的應用。在WebSphere Process Server V6.0.1中,服務元件及SCA在架構中的作用如圖 2所示:

圖2: WebSphere Process Server V6.0.1的架構環境


我們可以從圖 2 中看到服務元件架構在WebSphereProcess Server中的基礎地位,也可以看到各種與業務相關的服務元件或技術相關的輔助服務元件的關係。關於WebSphere Process Server的體系架構這裡不展開論述,具體請參考developerWorks專刊,2005年第三期的文章――WebSphere Process Srever V6體系結構概述。

SCA服務元件與傳統元件的主要區別在於:

1. 服務元件往往是粗粒度的,而傳統元件以細粒度居多。

2. 服務元件的介面是標準的,主要是WSDL介面,而傳統元件常以具體API形式出現。

3. 服務元件的實現與語言是無關的,而傳統元件常繫結某種特定的語言。

4. 服務元件可以通過元件容器提供QoS的服務,而傳統元件完全由程式程式碼直接控制。

1.2.2 服務模組(Module)

服務模組(簡稱模組)由一個或多個具有內在業務聯絡的服務元件構成。把多少服務元件放在一個模組中,或者把哪些服務元件放在一起主要取決於業務需求和部署上靈活性的要求。模組是SCA中的執行單位,因為一個SCA模組背後對應的是一個J2EE的企業應用專案。這裡之所以說是"背後",原因是我們在開發工具WID(WebSphere Integration Developer V6.0)中,通過業務整合透檢視看到都是SCA級別的元素。但是當你切換到J2EE透檢視你就會發現這些SCA元素與實際J2EE元素之間的對應關係。因此,在WID中構建一個模組就相當於構建一個專案。另外,由於模組是一個獨立部署的單元,這給應用的部署帶來很大的靈活性。比如,只要保持模組介面不變,我們很容易通過重新部署新的模組而替換原有的業務邏輯,而不影響應用的其它部分。

由於一個模組中往往會包含多個服務元件,那我們如何來構建這些服務元件之間的相互呼叫關係呢?在WID工具中,我們只要簡單地通過介面與引用之間的連線,就可以指定它們之間的呼叫關係而不需要寫一行程式碼。另外,我們可以在這些連線上面設定需要的QoS要求,比如事務,安全等。

1.2.3 匯入(Import)和匯出(Export)

使用者實際的應用經常是比較複雜的,因此實際的應用通常需要多個模組才能滿足要求,而且這些模組之間又往往存在相互呼叫的關係。

另外模組中服務元件除了呼叫別的服務元件之外,也需要呼叫已有的一些應用,或者是讓一些已有的應用來呼叫模組的服務,而這些應用可能不是基於SCA架構的。為了解決上述問題,在模組中我們引入了兩個特殊的"端點",一個是匯入(Import),它的作用是使得模組中的服務元件可以呼叫模組外部的服務。另一個是匯出(Export),它的作用是使得模組外部的應用可以呼叫模組中的服務元件。

由於涉及到模組內外的呼叫,因此需要指定專門的繫結資訊。這些繫結資訊包括了目標服務或源服務的呼叫方式,位置資訊,呼叫的方法等。目前,在WebSphere Process Server V6.0中,匯入端點提供了四種繫結方式,包括:JMS繫結,WebService繫結,SCA繫結和無狀態會話BEAN的繫結。匯出端點提供了三種繫結方式,包括:JMS繫結,WebService繫結和SCA繫結。對於SCA模組之間的呼叫,我們可以非常方便的把繫結方式設定為SCA繫結,但是對於非SCA模組與SCA模組之間的呼叫我們只能選擇其它繫結方式。

1.2.4    共享庫(Library)

當我們在構建了多個模組的時候,如果有一些資源可以在不同模組之間共享,那麼我們可以選擇建立一份可以在不同模組之間進行共享的資源,而不是在不同模組中重複建立。共享庫就是存放這些共享資源的地方。共享庫可以通過與模組類似的方式在WID中建立,但是共享庫包含的內容只有:資料定義,介面定義,資料對映和關係。與模組最大的區別使共享庫不包含服務元件,因此也就不包含業務邏輯。從包含的功能來看,我們可以把共享庫看作是模組的一個子集。當一個模組需要用到共享庫中的資源的時候,我們只需要使模組依賴於共享庫即可。從部署的角度,一個共享庫會對應一個JAR包。在部署的時候,模組所對應的J2EE企業應用會會自動包含所依賴的共享庫JAR包。這裡特別要注意的是,這裡的共享庫概念與WebSphere應用伺服器中的共享庫不是一個概念,它們之間沒有任何聯絡,因此不要混淆。

1.2.5 Standalone Reference

模組中的服務元件是不能直接被外部Java程式碼使用的,為了外部的Java程式碼,比如JSP/Servlet使用模組中的服務元件,WID工具在模組中提供了一個特殊的端點,叫做Standalone Reference。這個端點只有引用(Reference),而沒有介面(Interface)。只要把這個端點的引用連線到需要呼叫的服務元件的介面,外部的Java程式碼通過這個引用的名稱來呼叫相應的服務元件了。具體如何呼叫請參考後面例子的實際程式碼。

至此,與服務模組相關的主要概念已大概介紹完了,它們之間的關係如圖 3 所示:

圖3:服務模組總覽圖


1.3       同步呼叫和非同步呼叫

我們知道,常見的方法呼叫都是同步呼叫,這種呼叫方式是一種阻塞式的呼叫方式,即客戶端(主呼叫方)程式碼一直阻塞等待直到被服務端(被呼叫方)返回為止。這種呼叫方式相對比較直觀,也是大部分程式語言直接支援的一種呼叫方式。但是,如果我們面對是基於粗粒度的服務元件,面對的是一些需要比較長時間才能有響應的應用場景,那麼我們就需要一種非阻塞式呼叫方式,即非同步呼叫方式。

SCA程式設計模式提供了三種方式的非同步呼叫,它們分別是:

1.      單向呼叫方式。

2.      延遲響應方式。

3.      請求回撥方式。

單向呼叫

單向呼叫方式是最為簡單的非同步呼叫方式,在這種呼叫方式中,客戶端發出請求之後就不再關心服務端的情況,包括是否執行成功,返回值是什麼等等。我們可以用下面的圖 4示來描述這種單向呼叫方式:

圖 4:單向呼叫


單向呼叫方式是一種不管呼叫結果的方式,但是在很多情況下我們是需要知道呼叫結果的。我們需要知道呼叫是否成功,需要知道呼叫的結果,就算呼叫失敗我們也希望知道錯誤程式碼等資訊。在這種情況下,延遲響應和請求回撥就是兩種能夠讓我們知道呼叫結果的方式。

延遲響應方式

延遲響應方式是指客戶端在發出呼叫請求之後繼續執行,但是經過一段時間之後,客戶端再呼叫相應的方法去檢索返回結果,並通過引數指定如何根據呼叫的結果而執行進一步動作。由於是非同步呼叫方式,因此,在第一次發出呼叫請求的時候,服務端需要返回一個稱為票據(Ticket)的物件。這個物件會作為第二次發出檢索結果請求時的一個引數。顯然,這個Ticket物件的作用與WEB程式設計的SessionID非常類似。我們可以用圖 5 來表示延遲相應呼叫方式:

圖 5:延遲響應呼叫方式


請求回撥

與延遲響應方式類似,請求回撥方式也能得到服務端的響應,但是不同的是這個響應是由服務端通過回撥方式來觸發的,而不像延遲響應方式由客戶端來主動檢索的。請求回撥方式的原理與許多程式語言中的回撥機制類似,不同的是這裡實現的層次比較高一點。我們可以用圖6來表示請求呼叫方式:

圖 6:請求回撥方式


1.4 SCA客戶端的兩種呼叫方式

從介面的角度,SCA的客戶端程式設計模型有兩種方式:

1.靜態呼叫方式

2.動態呼叫方式

靜態呼叫方式

靜態呼叫方式是一種型別安全的方式,也是在一般Java程式設計中最為常見的方式。所謂型別安全指的就是在編譯的時候就做型別的檢查,而不是等到執行的時候發現型別錯誤問題。說明示例如下:

MyServiceImpl myService = (MyServiceImpl)serviceManager.locateService("myService");
myService.someMethod("input");

在SCA客戶端程式設計中,靜態方式就是直接拿到實際實現的介面型別,也即直接拿到Java介面。

動態呼叫方式

與靜態呼叫方式相對,動態呼叫方式是一種非安全的方式。它的優點是呼叫非常靈活,但同時帶來的不利之處是部分問題在編譯的時候是發現不了的,只有等到執行的時候才能發現。說明示例如下:

Service myService = (Service)serviceManager.locateService("myService");
DataObject input = ...
myService.invoke("someMethod","input");

像上面例子所示,在動態呼叫方式中,客戶端通過invoke方法的字串引數的方式來指定具體要呼叫的方法名稱。很顯然,在這種方式下,如果方法名有誤是不能在編譯時發現的。

關於動態呼叫方式另外要注意的一點是,在這種呼叫方式下,所有引數傳遞都是通過DataObject的方式,即SDO的方式。哪怕實際引數只是一個字串,也需要包裝成一個DataObject的方式。

介面型別與呼叫方式

實際上客戶端採用哪種呼叫方式是與介面型別有密切的關係。當提供的介面型別是WSDL型別的,那麼客戶端的呼叫方式只能是動態呼叫方式。由於WSDL是SCA模型中主要的介面方式,這樣就導致動態呼叫方式在SCA程式設計模型中非常普遍。但是如果提供的介面型別時Java型別的,那麼客戶端的呼叫方式可以是動態呼叫方式,也可以是靜態呼叫方式。



相關文章