使用服務組件架構(SCA)從不同技術調用組件

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  
服務組件架構(SCA)是一項可以抽象底層計算機服務的新技術,這樣,系統就可以更加靈活地合併由不同技術實現的子系統。SCA 將業務邏輯中有關訪問技術、實現和協議的大量細節移動到中間件層中。這種抽象對於某些開發人員來說是有代價的。因為業務應用程序將變得難於理解和調試。通過本文了解如何針對不同的協議綁定和實現類型執行組件調用。本文的示例使用了開源的 Apache Tuscany SCA 運行時來解釋底層複雜性。

簡介

在商業世界中有兩個重要的驅動因素:變化和異構性(heterogeneity)。不論您當前使用何種業務解決方案,都必須改變它,添加新特性,進行更新以獲得更好的服務,或者進行修改以滿足供應商的要求。這些驅動因素對加快業務解決方案的面市產生了巨大的壓力。企業從頭到尾設計大型項目並控制所有子系統的時代已經一去不返了。

SCA 是應對變化性和異構性的一項新技術。通過大量抽象底層實現技術,SCA 使系統在合併使用不同技術實現的子系統時可以更加靈活並迅速適應變化。SCA 將業務邏輯中有關訪問技術、實現和協議的大量細節移動到中間件層中。

一些技術架構師和開發人員在實現樣例 SCA 或更新現有服務方面邁出了第一步。隨著技術消費者的日漸成熟,仍然存留了大量問題,比如:

  • SCA 組件之間究竟是如何通信的?
  • 當一個客戶機程序與我的 SCA 應用程序通信時,SCA 運行時如何對我實現調用方法?
  • 當我的 SCA 應用程序遇到問題時,如何解釋運行時調用堆棧上出現的各種類?

在本文中,將解答以上這些問題。

SCA 運行時

本文使用 Apache Tuscany SCA 運行時環境作為示例,原因如下:

  • Apache Tuscany 是 SCA 的一個開源實現,並且可以免費下載。您可以安裝 Tuscany 和 Eclipse 開發平台 來實踐本文的示例。
  • Tuscany 是獨立於供應商和平台的。它可以獨立運行,也可以與來自不同供應商的伺服器(Tomcat、JBoss、Geronimo、IBM® WebSphere®、WebLogic)配合使用,並且可以在多個平台上使用(Microsoft® Windows®、Linux® 和 Mac OS)。
  • Tuscany 使用了本文討論的諸多協議綁定和實現。Tuscany 是適合解釋如何對 SCA 開發人員隱藏底層實現複雜性的優秀平台,使您能夠將精力放在修改併合並各種異構子系統上。




基本 SCA 概念

如果您對基本的 SCA 術語不了解,那麼本節將簡要介紹許多在 SCA 實現中共享並且在最新 Open SOA 規範 中標註的術語。

SCA 應用程序由集合(assembly)執行建模。一個 SCA 集合 包含一組工件以及將這些工件鏈接在一起的連接。集合存儲在一個複合文件(composite file)中。複合文件 常被描述為一個 XML 文件,其中包含各種 SCA 片段及它們之間的連接。複合文件被載入並準備好在 SCA 運行時(例如 Tuscany)中運行。圖 1 展示了一個示例集合。


圖 1. 典型 SCA 集合


組件 是指一個基本的 SCA 工件,是業務應用程序的構建塊。它提供基本的業務功能,比如股票報價服務或計算器服務。組件可以具有一些屬性來控制業務服務的行為,並且提供組件的配置。一個 SCA 組件可以通過多種技術實現。SCA 規範定義了一組基本的實現類型(Java™ 技術、BPEL、J2EE 和 Spring),並且允許其他 SCA 組件進行遞歸組合。Tuscany 提供了額外的類型,包括腳本語言(JScript、Groovy、PGP、Python、Ruby)和 OSGi。實現類型用於合併異構子系統和重用現有代碼。

SCA 組件的功能被作為服務提供給其他組件;一個 SCA 組件可以通過一個引用(reference)來利用服務。服務和引用被關聯在一起並顯示出來,並通過推廣發布到外部世界中。每個服務或引用都有一個介面,將業務介面描述為一組方法。每個方法有一個名字、若干參數和一個返回值。SCA 使用一個 Java 語言介面或通過一個 Web Services Description Language (WSDL) 文件定義這些介面。每個服務和引用通過一個訪問綁定 來訪問。綁定定義了用來訪問服務或引用的協議。目前,SCA 規範包含了一組基礎的流行綁定技術,比如 HTTP、JMS、Web 服務和 SCA(通常在兩個組件運行在相同 Java 虛擬機上並且沒有特別指定綁定時使用)。

Tuscany 提供了額外的一組有用綁定,幫助支持 Web 2.0 風格的應用程序、Atom、RSS、JSON/RPC 等等。如圖 2 所示,Tuscany 負責從各種技術中獲取特定於協議的消息,並將之轉換為業務組件可以使用的形式。業務組件實現對這些數據進行處理並傳遞迴 Tuscany SCA 運行時。再強調一次,我們的目標是合併並重用現有的訪問技術,同時讓業務組件開發人員能夠將側重點放在業務功能方面。


圖 2. SCA 運行時堆棧


最後,在調用業務介面中的每個方法時,作為參數提供給方法並從調用返回的數據將通過數據綁定提取。常見數據類型包括 Java 對象、XML 文檔和服務數據對象(Service Data Objects,SDO)。Tuscany 可以在不同數據類型之間自動轉換,為提供者和客戶機之間的數據流動提供便利。但是本文的重點並非數據綁定,而是這一術語的各種應用。

本節重點介紹 SCA 為業務應用程序開發人員提供的各種抽象。介面當前使用 Java 語言或 WSDL 指定。訪問綁定使用多種協議(HTTP、JMS、Web 服務、Atom、JSON/RPC)實現。組件實現可以通過多種技術(Java 技術、BPEL、SCA、Spring、J2EE、Scripting 語言、OSGi)獲得。本文餘下的部分將解釋這些技術如何交互,從而使您理解從服務調用到實現中的業務方法調用這一底層路徑。





場景

本文示例展示了一個簡單業務應用程序的演變過程。您可以 下載 場景示例的源代碼(應用程序很簡短,並且針對示例的目的進行了簡化)。

對這個業務服務的惟一要求就是將兩個數字相加。發布計算器服務供客戶機調用。此計算機被連接到只有一個功能的 add 服務:將兩數相加並返回總和(例如
double add(double o1, double o2) )。假設介面使用 Java 語言指定,並且服務也通過 Java 語言實現。圖 3 展示了這個 SCA 集合。


圖 3. 計算加法的 SCA 計算器組件


指定了計算器組件和它的實現后,這個組件將引用 add 服務組件及其實現。清單 1 展示了此業務應用程序的 SCA 複合文件。可 下載 該組件及其他組件的源代碼。


清單 1. 計算器複合文件
				  <composite xmlns="http://www.osoa.org/xmlns/sca/1.0"      xmlns:sample="http://sample"      name="Calculator">       <component name="CalculatorServiceComponent">        <implementation.java class="calculator.CalculatorServiceImpl"/>             <reference name="addService" target="AddServiceComponent"/>     </component>         <component name="AddServiceComponent">        <implementation.java class="calculator.AddServiceImpl"/>     </component>  </composite>  

假設客戶需求增長,並且需要一項可以計算減法的新服務。然而,有一種 Web 服務可以將介面指定為 WSDL 文檔並且被實現為一個 Java 程序。此 Web 服務可以通過 Web 服務訪問綁定進行訪問。因此,通過添加一個引用和訪問減法服務的組件,就可以輕鬆地向 SCA 複合文件添加新的需求。


清單 2. 包含新服務的計算器複合文件
				  <composite xmlns="http://www.osoa.org/xmlns/sca/1.0"      xmlns:sample="http://sample"      name="Calculator">       <component name="CalculatorServiceComponent">        <implementation.java class="calculator.CalculatorServiceImpl"/>             <reference name="addService" target="AddServiceComponent"/>        <reference name="subtractService" target="SubtractServiceComponent"/>     </component>         <component name="AddServiceComponent">        <implementation.java class="calculator.AddServiceImpl"/>     </component>          <component name="SubtractServiceComponent">        <implementation.java class="calculator.SubtractServiceImpl"/>        <service name="SubtractService">          <interface.wsdl interface="http://calculator#wsdl.interface(SubtractService)" />          <binding.ws uri="http://localhost:8080/SubtractServiceComponent"/>        </service>     </component>    </composite>  

要實現業務示例的演變,我們需要添加對乘法和除法服務的需求。這些服務可以以 JScript 和 Groovy 實現的形式獲得。Tuscany 允許您輕鬆地將這些服務添加到複合文件中。業?應用程序表示現在應當如圖 4 所示。


圖 4. 包含 4 個服務的 SCA 計算器


在應用程序的最後一個 SCA 複合文件中,注意添加的 JScript 和 Groovy 組件是對 SCA 規範的特定於 Tuscany 的擴展。因此,一個新的名稱空間屬性為這些組件引入了特定於 Tuscany 的語法。


清單 3. 包含 4 個服務的計算器複合文件
				  <composite xmlns="http://www.osoa.org/xmlns/sca/1.0"      xmlns:sample="http://sample"      xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0"      name="Calculator">      <component name="CalculatorServiceComponent">       <implementation.java class="calculator.CalculatorServiceImpl"/>              <reference name="addService" target="AddServiceComponent"/>       <reference name="subtractService" target="SubtractServiceComponent"/>       <reference name="multiplyService" target="MultiplyServiceComponent" />       <reference name="divideService" target="DivideServiceComponent" />    </component>        <component name="AddServiceComponent">      <implementation.java class="calculator.AddServiceImpl"/>    </component>        <component name="SubtractServiceComponent">       <implementation.java class="calculator.SubtractServiceImpl"/>       <service name="SubtractService">          <interface.wsdl interface="http://calculator#wsdl.interface(SubtractService)"/>          <binding.ws uri="http://localhost:8080/SubtractServiceComponent"/>               </service>    </component>      <component name="MultiplyServiceComponent">       <tuscany:implementation.script script="calculator/MultiplyServiceImpl.js"/>    </component>      <component name="DivideServiceComponent">       <tuscany:implementation.script script="calculator/DivideServiceImpl.groovy"/>    </component>  </composite>  

該場景可以讓您做出兩項快速修改,並向初始業務應用程序添加三個組件。新的組件將在初始組件的基礎上使用不同技術實現和訪問。SCA 可以對變化的和不同種類的業務需求做出響應。

Tuscany 運行時簡化了對這些技術的訪問,並且 SCA 複合文件相對來說較少包含特定於技術的內容。然而,我們並不了解這些技術在底層是如何調用的。現在讓我們深入探究一下 SCA 的內部。





Tuscany 調用架構概述

SCA 包含大量有關訪問技術、實現和協議的細節,並將它們從業務邏輯轉移到中間件層。這對於業務應用程序開發人員來說是件好事,但是對於軟體開發人員有什麼影響呢?本節將探討 Tuscany 框架的內部,展示業務組件實現中的典型調用路徑。

要運行 SCA 業務應用程序,SCA 運行時(比如 Tuscany)首先需要載入並配置 SCA 複合文件。對各個複合文件工件進行檢查,然後使用工廠方法在內存中實例化不同對象。第二步是實例化用來連接組件的運行時連接(runtime wire)。在這個步驟中,將通過複合文件中提到的綁定針對組件引用和組件服務創建運行時連接。

運行時連接 是一個調用鏈集合;業務介面中的每個方法都有一個調用鏈。將創建一個處理程序,它充當一個消息交換台操作程序(switchboard operator)並將每個方法調用傳遞到相應的調用鏈。每個調用鏈由一組調用器(invoker)和攔截器(interceptor)組成。調用器 為綁定協議和實現技術提供調用邏輯。攔截器 是一種特殊的調用器,它提供其他的功能,比如數據轉換、安全性和事務控制。對於組件引用,將創建一個運行時連接來通過所選的綁定表示出站(outbound)調用。對於組件服務,將創建一個運行時連接來表示對實現類型的入站(inbound)調用。回調鏈也被添加到運行時連接中以提供對組件的反向回調。

當消息從計算器組件傳遞到 add 組件時,遵循計算器應用程序中的調用路徑。

  1. 一個調用被分配到 InvocationHandler。在本例中,這是一個基於 Java 技術的處理程序。
  2. InvocationHandler 查找正確的 InvocationChain。本例查找 add 方法鏈。
  3. 各種調用器和攔截器創建一條消息,設置有效負荷,設置 TargetInvoker,並將消息沿著調用鏈傳輸。
  4. TargetInvoker 通過底層協議發布消息。一個 SCA 組件通過參照另一個 SCA 組件傳遞一些 double 值。因此沒有出現數據轉換或協議轉換。
  5. 在接收端,一個偵聽程序將從底層協議獲取消息並將其傳遞給其中一個接受組件的調用鏈。再次強調,SCA 組件是使用 Java 技術實現的。將創建與 add 方法對應的鏈。
  6. 調用鏈找到 add 服務的 add 方法並調用此方法。組件實現將數字相加並返回總和。
  7. 反向路徑被送回到調用組件。

此路徑如下所示。


圖 5. 從源到目標的 SCA 調用


Tuscany Java 到 Java 的調用

當使用調試器調試示例 SCA 應用程序並在 AddService add 方法上設置斷點時,將看到如清單 4 所示的調用堆棧跟蹤。計算器服務實現調用方位於頂部。add 方法調用服務的 Java 代理表示。JDKInvocationHandler 將消息傳遞給合適的調用鏈。特殊的 PassByValueIntercepter 查找 SCABindingInvoker 並通過它傳遞消息。SCABindingInvoker 在服務端查找鏡像 PassByValueInterceptor。消息被轉換為 Java 調用,後者將調用 add 服務組件實現。


清單 4. Java 調用堆棧
				  CalculatorServiceImpl.add(double, double) line: 54    $Proxy7.add(double, double) line: not available	  JDKInvocationHandler.invoke(Object, Method, Object[]) line: 155	  JDKInvocationHandler.invoke(InvocationChain, Object[], RuntimeWire, EndpointReference)      line: 287	  PassByValueInterceptor.invoke(Message) line: 112	  SCABindingInvoker.invoke(Message) line: 61	  PassByValueInterceptor.invoke(Message) line: 112	  JavaImplementationInvoker.invoke(Message) line: 132	  Method.invoke(Object, Object...) line: not available	  DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: not available	  NativeMethodAccessorImpl.invoke(Object, Object[]) line: not available	  NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available    AddServiceImpl.add(double, double) line: 30	  

從計算器服務向 add 服務發出一個簡單的 add 調用似乎使用了一個很長的調用鏈!確實很長,但是這種從業務領域到底層技術領域的抽象在每個業務應用程序中都會出現。如果您要自己實現這類特性,那麼必須肩負起實現和維護這一層的重擔。

Apache Tuscany 的 SCA 運行時提供了這種實現並為您完成了這些工作。它具有如上所示的簡單的 Java 到 Java 的調用以及大量服務和引用綁定,具有許多組件實現類型。技術實現被從業務邏輯中分離出來,因此大大簡化了應用程序。

Tuscany Java 到 WSDL 的調用

這個來自 SCA 應用程序的示例具有更加複雜的調用,包括計算器服務和減法服務方法等等。回想一下,兩種服務都使用 Java 技術實現,但是在這裡,減法服務使用 WSDL 介面描述,而調用通過一個 Web 服務訪問綁定運行。SCA 使您可以引用並訪問各種不同的技術。

在本例中,應用了相同的一般調用路徑,但是路徑中出現了更多的攔截器。Tuscany 運行時現在必須將基於 Java 技術的調用轉換為底層協議的 Web 服務消息。例如,將調用 DataTransformationInterceptor 將 double 值的 Java 表示轉換為原生的 Web 服務 XML 表示。圖 6 展示了對目標組件的源組件調用的多個階段,並且圖 5 中不同顏色顯示的每個階段表示其在調用中的角色。


圖 6. 含有中間類的 SCA 路徑


再重申一次,如果將這個計算器 SCA 應用程序和 Tuscany 運行時放到 Java 調試器中,並且對服務的 subtract 方法設置了一個斷點,那麼將看到類似清單 5 的輸出(這個推展僅展示了調用的接收端)。Web 服務通常位於 HTTP 協議層之上,而 HTTP 層以請求的形式接收到一個消息調用並將此請求傳遞給底層 Web 服務層。

在堆棧的最上端,底層技術 Web 服務引擎接收調用。由於 Apache Tuscany 使用 Axis2 Web 服務引擎,可以看到在堆棧中有幾個 Axis2 類。Tuscany RuntimeWire 調用器隨後接收本地消息並找到合適的調用鏈來執行調用。此調用首先調用 DataTransformationInterceptor,這將把 Web 服務表示轉換為一個 Java double。JavaImplementationInvoker 查找並對 subtract 服務調用 Java subtract 方法。


清單 5. Web 服務調用堆棧
				  AxisEngine.receive(MessageContext) line: 176	  Axis2ServiceInOutSyncMessageReceiver(AbstractMessageReceiver).receive(MessageContext)      line: 100	  Axis2ServiceInOutSyncMessageReceiver(AbstractInOutSyncMessageReceiver).     invokeBusinessLogic(MessageContext) line: 42	  Axis2ServiceInOutSyncMessageReceiver.invokeBusinessLogic(MessageContext, MessageContext)      line: 70	  Axis2ServiceProvider.invokeTarget(Operation, Object[], MessageContext) line: 736	    RuntimeWireImpl.invoke(Operation, Message) line: 158	  RuntimeWireInvoker.invoke(Operation, Message) line: 98	  RuntimeWireInvoker.invoke(RuntimeWire, Operation, Message) line: 104	  RuntimeWireInvoker.invoke(InvocationChain, Message, RuntimeWire) line: 129	  DataTransformationInterceptor.invoke(Message) line: 78	  JavaImplementationInvoker.invoke(Message) line: 132	  Method.invoke(Object, Object...) line: not available	  DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: not available	  NativeMethodAccessorImpl.invoke(Object, Object[]) line: not available	  NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available    SubtractServiceImpl.subtract(double, double) line: 27	       





結束語

儘管示例 SCA 應用程序在概念上非常簡單,但是其實現卻相當複雜。計算器應用程序涉及 4 個不同的服務。每個服務通過不同的技術(Java 技術、Web 服務、HTTP、JScript 和 Groovy)實現或訪問。對於某些架構來說,可能不允許將這些完全不同的技術集成在一起。技術層和業務層可能一直都是混合在一起的。一些開發人員將花費大量時間來從某個技術領域轉移到另一個他們認為是最好的技術領域。

SCA 與上述架構完全不同。它允許您利用現有的技術並將它們合併到同一個應用程序中。這些技術按原樣導入,幾乎很少進行轉換和重新編碼。並且技術實現與業務邏輯被分離開來。任何一個 SCA 組件都可以換入或換出,或者託管在新的綁定或實現中,而且對整個應用程序的影響非常小。

付出很小的代價就能獲得 SCA 的這些優勢。幸運的是,Tuscany 等的 SCA 運行時可以為您完成消息傳遞、理解各種介面、與訪問和數據綁定交互,以及調用各種實現類型等全部工作。實際上,應用程序中的許多技術問題被轉移到了 Apache Tuscany 中間層中。有時,當在 SCA 應用程序中查找問題時,生成的調用路徑看起來有些複雜。本文通過一個 SCA 示例實現幫助您理解這些複雜性。(責任編輯:A6)






[火星人 ] 使用服務組件架構(SCA)從不同技術調用組件已經有503次圍觀

http://coctec.com/docs/linux/show-post-68872.html