未來整個應用程式合作是以網路為基礎,不分廣域網路或區域網路。如同現今微軟在 SOAP Tool Kit 中所示範的,透過自行撰寫的 Visual Basic 程式可以經由網際網路輕易地呼叫提供股票交易資訊的程式物件,以獲得最新的股票交易資訊。
或是透過網際網路呼叫可以將歐語系語言互翻的程式物件。假想你是一個提供中英文互翻的廠商,如今你賣的字典可以輕易地辦到歐語系加上中文的互翻能力。因為若有人需要將中文翻成德文,透過撰寫的程式將中文轉成英文後,再透過網際網路呼叫一個歐語系互翻的程式將英文再轉成德文,而不必撰寫任何其他的程式碼。
現今企業內的資訊系統漸漸開始強調整合,我相信這是企業 IT 下一階段的需求。在當下,大家要忙於建立某種系統,不管是 ERP、CRM、SCM、EIP、KM...。不久後,該有的系統都有了,他們將會發現分崩離析的獨立系統對企業局部的功能正常運作沒有什麼很大的益處,上述的系統都是操作型的系統,只能把事情做對,例如財務正確、客戶正確、生管正確等等。但就以公司經營的全局而言,卻不知道什麼是對的事情。
唯有全面的整合與分析才能突顯企業的策略與競爭力,也必須讓公司上下都能輕易取得正確有效的分析資訊,才有可能掌握先機,否則誠如筆者在某本管理書籍所看到的:「大家都以為公司決策者在做重大的運籌帷幄,殊不知下層經理人所提供的資訊都是錯誤的。」 在 IT 系統整合的需求下,服務導向(SOA)/訊息導向的概念應運而生,也就是各大系統都是另一個系統的 Service 或 Client,而負起穿針引線串聯各系統的技術就是 Web Service 與 SOAP 協定。
透過網路,這種程式物件不分企業、地域、國界地整合在一起,但需要有新的程式間互相溝通的協定。以往的 RMI/IIOP/DCOM 等等通訊協定太過繁複與專屬,且不適合以網際網路為溝通平台,所以由公開機構 W3C 來審定 SOAP 協定,提供所有軟體開發廠商有共通的程式溝通協定。
簡易物件存取協定 - SOAP
我們就來看看什麼是簡易物件存取協定(Simple Object Access Protocol,SOAP):簡而言之就是利用現存的網際網路架構讓應用程式之間可以彼此溝通,而不會被防火牆阻礙。在分散式的架構下及使用 XML 的環境中,SOAP提供兩個電腦系統之間交換的資料架構與型別。也因此可以簡單定義如下:
SOAP=HTTP+XML
在過去七年來,透過網際網路存取已經變成是較進步社會的基礎需求,紛紛在其上執行著各式各樣的通訊協定。但是直至目前為止,最廣泛被接受的通訊協定依然是HTTP,它在瀏覽器與 Web 伺服器之間溝通時使用,對於文字、圖形以及其他資訊的傳輸很有效率與彈性,而且它簡單易懂(機器看得懂,人也看得懂,這是網際網路上應用層協定的特色,諸如 SMTP、POP3、FTP...等等皆是如此)。
SOAP的優點
因為 SOAP 的資料描述方式是採用 XML,因而承襲了 XML 下列的好處:
- ● 容易使用與延伸:XML 技術的本身相當簡潔,且具有高度的延伸性。同時,一般的系統已經多多少少採用 XML 的技術,因此存取 XML 資料對開發各系統的程式設計師來說並不陌生。而大多數提供平台的廠家也都支援 XML,因此它是跨平台合作、交換資料的最佳選擇。
- ● 資料清楚明白:這是 XML 特色,一開始它的設計就是為了資料交換,在 XML Schema 的輔助下,讓資料的使用清楚明白。
- ● 容易建立、分析與處理:不管是提供給程式開發人員所使用的物件,或是編寫 XML 的工具程式都已經非常成熟,因此要建立、分析與處理 XML 文件不再是件困難的事。
未來網際網路上的系統需要自動完成合作,不再有人工參與。而且彼此的系統是各自以所熟悉的技術完成,這代表著系統不會遵循特殊的架構。有可能甲方的系統是Win32,使用的是COM+﹔而乙方的是UNIX作業系統,利用CORBA提供服務。
讓兩個系統透過網際網路溝通,僅僅用HTTP通訊協定本身提供的功能是不夠的,雖然HTTP本身的彈性很大,但它基本的設計並不適合呼叫遠端的程式物件。這種互動在區域網路內一般是使用Remote Procedure Call(RPC)模式,也就是使用者端程式傳出一些參數,透過與使用者端執行在一起的伺服代理程式、遠端和伺服程式執行在一起的使用者代理程式溝通,再由伺服器端的使用者代理程式和伺服程式溝通,並由伺服端回傳一些結果,循相反的路徑回給使用者端程式。
現今已有許多分散式物件通訊協定(distributed object protocols)提供遠端程式間的溝通。例如微軟的Distribured Component Object Model(DCOM)、Object Management Group的Internet Inter-ORB Protocol(IIOP)等等。所有這些服務都提供相同的服務,也就是讓使用者端可以觸發RPC到伺服端應用程式,並接到回傳結果。
在企業內部網路(Intranet)上使用分散式物件傳輸協定有很好的效果,但在公眾的網際網路上使用這些協定就有很多問題。任何連上網際網路的伺服器基本上都可以被任何網際網路的使用者存取,這導致需要較嚴謹的安全考量。
源於安全考量的電子服務標準協定
為了安全,大部分的企業都在它們內部與外部網路之間加裝防火牆,以防止網際網路上的大眾存取企業內部的伺服器。這些防火牆,例如微軟的Proxy伺服器,可以經由條件設定,阻止一些想進企業內部來的公眾網路需求,這可以大幅提昇內部系統的安全。
雖然防火牆是提供接上網際網路安全的基礎機制,但它卻會降低分散式物件通訊協定的使用效能。為了要解決這個問題,有識之士紛紛提出了各自的解決方案。在 1998 年,UserLand 公司的執行總裁 Dave Winner 主張透過 XML,讓 RPC 的通訊方式經由 HTTP 協定在網際網路上執行。
這個想法經由微軟加以改良,提出了實際可行的SOAP通訊協定,目前正在W3C審議中,幾乎所有的資訊大廠都表態支持。不久的未來即將可能成為在網際網路上提供電子服務的標準協定。
SOAP的物件溝通基礎規範
SOAP是一個像DCOM或其他分散式物件通訊協定的協定,讓使用者端與伺服端的RPCs可以溝通。但與其他類似協定不同之處,在於它支援防火牆的使用。同樣重要地,SOAP不是只設計用來針對某種物件技術的協定,它不像一些時下的分散式物件通訊協定,會被綁死在某一種特定的物件規格上,這個協定將可以被任何的物件使用。所以它將是兩大物件陣營COM 和 CORBA最好的溝通橋樑,讓彼此的物件程式可以跨平台、透過網際網路呼叫。
簡易物件存取協定如其名稱所言,要求定義要“簡易”,所以它只訂出物件溝通基礎規範,如:@內標:● 讓物件透過網際網路提出需求的方式標準化,以 HTTP 當傳輸的方式,以 XML 描述溝通的內容
● 建立可延伸的傳遞物件呼叫格式的承載
但它不定義一些一般分散式物件系統需要定義的
● 分散式系統資源回收(garbage collection)
● 雙向的 HTTP 溝通
● 物件參照
● 物件初始化
以上這些不明確定義的規格都交由各系統廠商自行實作。
SOAP 訊息的結構
SOAP 訊息的結構基本上有三塊:Envelope、Header 以及 Body,另外,當 Web Service 運行錯誤時,會傳回含在 Body 內的 Fault 區塊。這幾個基本區塊的功能如下:
- ● Envelop:代表 SOAP 訊息的 XML 文件的根節點。其內可以包含兩個區塊,選擇性的 Header 以及必定存在的 Body。
- ● Header:若 Header 區塊有出現,則必定緊接在 Envelope 元素之後。但它是選擇性的,所以也可以不出現。
- Header 主要是提供輔助資訊,在溝通中,不必然需要。一般可能將安全訊息、交易等資訊放在此處。在後文中,會利用此區塊來傳遞使用者的帳號資訊。
- ● Body:如果 Header 區塊未出現,Body 就緊跟在 Envelope 之後,若 Header 有出現,則 Body 跟在 Header 之後。Body 放的是使用者端與伺服器端,方法呼叫所傳遞的資料,這部分一定會出現,否則無法呼叫 Web Service。
- ● Fault:用來傳遞錯誤的訊息,如果 SOAP 封包內有 Fault 區塊,則該區塊一定出現在 Body 內,且只能出現一次。
以下是筆者直接透過封包擷取程式,將使用者端對 Web Service 的呼叫,以及伺服器端回應使用者的 SOAP 封包擷取下來,並整理如程式碼一及程式碼二的內容:
程式碼一:使用者端對 Web Service 呼叫的封包內容
POST /getwsdl/service1.asmx HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 1.0.3705.0)
Content-Type: text/xml; charset=utf-8
SOAPAction: http://myDemo/GetEmployee
Content-Length: 310
Expect: 100-continue
Connection: Keep-Alive
Host: byronnew
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetEmployee xmlns="http://myDemo/">
<intI>1</intI>
</GetEmployee>
</soap:Body>
</soap:Envelope>
程式碼二:Web Service 回應使用者端的封包內容
HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
Date: Tue, 15 Oct 2002 03:54:43 GMT
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Content-Length: 393
<?xml.version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetEmployeeResponse xmlns="http://myDemo/">
<Employee>
<LName>胡</LName>
<FName>百敬</FName>
<Title>顧問</Title>
</Employee>
</GetEmployeeResponse>
</soap:Body>
</soap:Envelope>
除了傳回一般函數的執行結果外,SOAP 也制定了錯誤訊息的傳遞方式,也就是上述的 Fault 區塊。
筆者同時在 Web Service 內的方法故意觸發例外狀況,該例外狀況透過 SOAP 封包回傳的內容如程式碼三所示:
程式碼三:Web Service 回應使用者端的 SOAP Fault 封包內容
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>System.Web.Services.Protocols.SoapException: 伺服器無法處理要求。 ---> GetWSDL.myExcept: 發生了很嚴重的例外狀況!!
at GetWSDL.Service1.ThrowExcept() in C:\BookSamples\ch09\GetWSDL\Service1.asmx.vb:line 72
--- 內部例外堆疊追蹤的結尾 ---</faultstring>
<detail />
</soap:Fault>
</soap:Body>
</soap:Envelope>
在 Fault 區塊內,可以包含四個子元素:
- ● faultcode:必須存在,用來定義錯誤。
- ● faultstring:必須存在,提供人類也可以閱讀的錯誤說明提示。
- ● faultfactor:選擇性存在,當 SOAP 訊息的最終目標不是當下的應用程式時,透過這個元素傳遞 URI 格式的來源位置。
- ● deatil:選擇性存在,應用程式與 Body 元素有關的特定錯誤訊息,如果 Body 內的某些內容無法處理時,會將原因寫在這個元素內。
因為我們透過上層應用程式架構丟出的例外類別,可以透過 SOAP Fault 封包傳遞,所以若使用者端的應用程式也是透過相同程式架構撰寫,經由 SOAP 協定與 Web Service 溝通,依然可以正常地擷取伺服器端所丟出的例外狀況。
筆者在此故意丟出自定的例外,若用 Visual Studio.NET 撰寫使用者端程式,透過代理程式呼叫,可以獲得一般的例外狀況,畫面如圖一所示:
《圖一 透過 Web Service 前端代理程式呼叫,可以透過一般的 try/catch/end try 完成例外處理 》 |
|
防火牆問題與SOAP解決方案
要了解為何防火牆會造成分散式物件通訊協定的問題,必須先了解到防火牆是如何分辨協定之間的不同。在TCP/IP的架構下,每一個被廣泛使用的協定都被賦予一個特殊的埠號(port number),而每一個使用該協定的需求封包都帶著這個埠號。例如 HTTP 協定的埠號是 80、FTP 是 21等等。大部分的防火牆有防止某個特殊協定的方法,就是針對埠號拒絕某種協定的通訊。通常防火牆是被設定成允許埠號 80 的運作的 - 如果該公司不拒絕使用 HTTP 的話。但大部分的防火牆會擋住其他的埠,因為它們假定利用其他的埠,對公司內部網路的運作來說都是有危險的。
但這也正是造成分散式物件通訊協定無法運行的原因。不像 HTTP、FTP 等其他著名的通訊協定,分散式物件通訊協定通常沒有使用一個大家都知道的埠號來溝通。相反地,這些通訊協定通常動態地被賦予一連串的埠號,埠號碼在被需求時任意產生。如果沒有防火牆擋在使用者端與伺服端之間,這種方式將可以很有效地運作。但若加了防火牆,則該通訊協定會因為防火牆不允許兩端任意使用任何埠號溝通而中斷。
上述問題目前存在許多種解決方式,例如某些防火牆可以被設定成允許某個範圍的埠號碼,而能進行溝通。若該分散式物件通訊協定也可以被設定成只用這個範圍的埠號碼,則這個方案便可行,使用者端與伺服端之間可以進行溝通。但比較注重安全的網路管理者將不會贊成開放任意一組埠號碼,因而導致這個方案並不完美。
另一個選擇是採用 COM 網際網路服務,讓傳統的 DCOM 封包在 TCP 上透過埠號 80 來傳遞。這在某些方面很有用,但這項技術只有微軟的 Internet Information Server 和 DCOM 在使用,所以不是一項完整的解決方案,我們需要一個更普遍且一般性的解決方案。
由於所有的防火牆幾乎都允許透過埠號80來溝通,所以透過埠號80來溝通的分散式物件通訊協定將是一個較好的方案。但這並不是說說那麼容易,因為埠號80已經用於 HTTP 協定的設定了,因此SOAP這個分散式物件通訊協定是架在 HTTP 協定之上的。
HTTP 通訊協定相當簡單,僅僅以少數基礎的動詞組成,如 GET、PUT、POST等等,而這些動詞在瀏覽器與伺服器之間傳遞。每一個動詞之後跟著一些資訊,這些資訊通常以簡易的字串方式傳遞。SOAP 不能改變任何的現狀,也不能要求增加 HTTP 現有的動詞。替代方案是 SOAP 將使用XML來定義需求與回應訊息的格式,並允許使用正常的HTTP POST 命令來傳遞這些訊息。所有的 SOAP 通訊都使用80埠,這也代表著在網際網路上,SOAP 可以透過任何的 Web 伺服器來溝通 - 防火牆將不再是一個問題。
SOAP 主要的設計目的之一,是保證它可以有效地使用既有的網際網路架構 - 也就是 HTTP、防火牆、代理伺服器(proxy)以及其他架構。例如 SOAP 可以使用 Secure Sockets Layer(SSL)通訊協定以加密維護安全、使用 HTTP 的連線管理機制等等。SOAP讓分散式物件通訊協定透過網際網路的溝通就像使用瀏覽器來存取網頁一樣方便。
潛力無限的SOAP
直到今天,各種 XML Web Service 的相關規格都還在研議發展中,我們已經擁有的只是非常基礎的規格,也就是透過 SOAP(Simple Object Access Protocol) 通訊協定,完成簡單的溝通基礎,但若要進一步提供嚴謹的商業服務卻還是力有未逮。因為諸如交易管理、訊息交換品質、資料安全、訊息繞送、附加檔案...等等規格都還需要制定。
微軟、IBM、BEA以及陸陸續續在後來加入的公司,為了提供更有彈性、穩定的 XML Web Service,一起通力合作,對上述的需求及相關規格提出許多草案。這許許多多的建議案合稱為 Global XML Web Service Architecture(GXA)。各軟體公司再根據該規格,在自己的平台上實做出應用程式平台。例如微軟最近提供的 Microsoft Web Services Enhancements 2.0 函式庫。
就是遵循 GXA 以 .NET Framework 函式庫的形式實做了 WS-Security、WS-Policy、WS-Trust、WS-Secure Conversation、WS-Attachments 和 DIME 等定義的物件類別,讓你透過 SOAP 通訊協定傳送訊息時,可以增加一些 SOAP 原先沒有定義,但實做 Web Service 時可能需要的功能。
這些規格的制定只是開始,不是最終的解決方案,但它開啟了未來的光明之路。當然,規格的制定都需要靠資訊界攜手合作,尤其 XML Web Service 的特色是聯邦式(Federated),也就是在一定的基本規則上可以自訂規則來玩,並不一定要經過某個中心,或受什麼控管,這就更需要大家的參與,XML Web Service 才有美好的未來。
雖然目前已有許多分散式物件通訊協定被創造出來,但尚未有一個能夠不被改變,就適用於現今的網際網路上的。藉由提供一個架在 HTTP 之上,簡單、有彈性的機制來傳送需求與回應,SOAP 讓當下觸發遠端函數不需要有任何改變。讓應用程式可以透過網際網路存取不是一件簡單的事,且它並未被綁死在任何一個單一的物件模型,可預期這項新的技術可以被用在許多不同情況,相當有潛力。