Web Services 學習筆記(一)
作者:蔡煥麟
日期:Apr-3-2002
摘要:簡述 Web Services 的概念、由來、運作方式及應用時可能遭遇的問題,並分別以 Delphi 6 和 VisualStudio.NET 示範撰寫 Web Services 用戶端程式的步驟。
什麼是 Web Services?
平台中立的網路服務
Web Services 是一種平台中立的網路服務,應用程式可以透過 URL 指定存取 internet 上任何一台電腦提供的服務,不管對方的電腦是什麼作業平台或應用程式的類型,雙方只要遵循標準的協定就可以溝通。
分散式應用程式的基石(building blocks)
基於其平台中立的特性,軟體開發人員可以將設計好的 Web Services 公佈在 internet 上供其他應用程式使用,其他的開發人員則可以重複使用這些現有的服務來建構分散式應用程式,而無須花時間重新設計相同功能的軟體元件。
Web Services 使得「軟體即服務」的觀念更容易落實,同時也意味著分散式架構所涵蓋的範圍將更廣。
為什麼要有 Web Services?
前面已經大略點出,Web Services 基於其平台中立以及 internet 無遠弗屆的特性,將可提高軟體元件的重複使用率,這是它的好處之一,除此之外,我們還可以從企業的需求以及技術面兩種角度來探討為什麼需要 Web Services。
企業的需求
早期企業對企業之間的資料交換是以 EDI(Electronic Data Interchange,電子資料交換)達成,但由於 EDI 多為昂貴的專屬系統,使用特定的協定與資料格式,因此維護成本較高,擴充也不容易。隨著網際網路的興盛,具備高度開放性的架構、協定、及資料格式便大受歡迎,例如:TCP/IP,HTML,XML....等,並且促成了一波企業對客戶(B2C),企業對企業(B2B)的電子商務熱潮。而在 B2B 方面則逐漸形成了電子交易市集(eMarketplace)的商務模式,此模式由第三方提供一個交易場所(網站),讓各商家在此地進行交易,資料輸入仍以人工作業為主,以目前各行業競爭之激烈,速度可說是勝負的關鍵,如果能夠將人工輸入資料的方式改成電腦之間自動交換資料就可以大幅縮短企業間溝通及資料交換的時間,進而提昇企業的競爭力與反應速度。集各項公開標準於一身的 Web Services 正好符合這個需求。
由此觀之,也能看出 Web Services 的另一項特點:把以往使用者與應用程式的互動的情景,轉變成應用程式與應用程式之間的互動。
現有技術的不足
若以技術的角度來看為什麼需要 Web Services,可以先看看現有的分散式架構有何不足。目前大多數的分散式應用系統都是以遠端程序呼叫(Remote Procedure Call,RPC)的方式存取另一台電腦上的服務,例如:Microsoft 的 Distributed Component Object Model(DCOM),Sun 的 Remote Method Invocation(RMI),OMG 的 Common Object Request Broker Architecture(CORBA) 等,這些以 RPC 為基礎的分散式架構提供了開發人員熟悉的程式撰寫方式(函數呼叫)以及位置透明化(location transparency)的優點,但是它有以下缺點:
緊密耦合。用戶端與伺服器程式之間要規定詳細的呼叫方式,而且用戶端得事先知道如何存取這些服務的相關細節(例如函式有哪些參數及其型態),伺服器這邊稍有改變可能就會令用戶端無法執行。
只能同步執行(synchronous calls)。用戶端呼叫伺服器的某個程序時,必須等該程序執行完畢之後才能繼續其他動作,期間使用者能做的只有等待。儘管可以使用多執行緒的技巧來解決,但卻增加了程式的複雜度,程式也比較難撰寫。
當應用程式需要以非同步的方式執行工作時,便衍生出另一種所謂的訊息導向的架構,例如:Microsoft 的 MSMQ,IBM 的 MQSeries 等。有別於 RPC 的程序呼叫方式,這種架構使用非同步訊息傳遞的機制,訊息送出後用戶端便可以繼續執行其他工作,訊息保證會送達目的地,至於何時送達則不確定,這是它最大的特色,而其缺點為:
先收到的訊息先處理(佇列),無法提供特定工作流程(workflow)的執行順序。
程式設計師必須處理訊息封包的包裝、解讀與驗證,是一項不輕的負擔。
各家廠商提供的解決方案彼此不相容。
不管是 RPC 還是訊息導向的架構,它們都有一個共同的缺點,就是會跟特定的作業環境或軟體綁在一起,而且各種產品使用不同的傳輸協定或資料格式,使得彼此不能相互溝通。另外,DCOM、RMI、CORBA 等二進位協定通常會被防火牆擋在外面,使外界無法直接存取企業內部的資訊服務,若要讓它們能夠穿過防火牆,網管人員就必須在牆上打洞,如此勢必引發網路安全的問題,這也是現有的分散式架構中一個比較讓人頭痛的地方。
為了解決這些問題,Web Services 便應運而生。它具有以下特點:
寬鬆的(loosely-coupled)分散式架構。
平台中立,與實作(開發工具、程式語言)無關。
無狀態(stateless)。
提供同步與非同步的程序呼叫。
容易穿越防火牆。
但並不是說 Web Services 就可以完全取代傳統的分散式技術,只能說各有其適用的時機吧,在評估要使用哪一種技術來開發應用程式時,除了瞭解技術本身的優缺點,也要確實瞭解應用程式的需求及環境的限制,才不會發生以尖端科技製造無用軟體的情形。
Web Services 是如何運作的?
Web Services 要能運作,首先必須解決的問題是:
應用程式如何透過 internet 遂行遠端程序呼叫,而且不用知道對方的作業環境及應用程式型態?
用戶端程式如何知道怎樣使用某個 Web Service?或者說,如何得知該服務的介面(提供哪些方法呼叫)?
當應用程式需要某種特定的功能時,怎麼知道網路上已經有人提供這類功能的 Web Services?到哪裡找到這些 Web Services?
第一個問題的答案是需要一個標準的訊息格式以便可以順利在各平台之間傳遞。第二個問題則需要一個描述 Web Services 的文件,用戶端可以透過解讀這個文件來了解如何使用它。第三個問題可以透過一個描述的答案則是要有一個類似目錄服務的機制,提供外界查詢現有的 Web Services。
Web Services 有三個重要的元素可以解決上述問題,它們是:
SOAP - 傳遞訊息的格式
WSDL - 描述服務的內容
SOAP Discovery - 尋找有哪些服務
也有人稱它們為 Web Services 三劍客,以下再個別進一步地說明。
SOAP
前面多次提及 Web Services 是平台中立的,這不僅指作業系統,連網站伺服器的品牌、應用程式的類型都沒有特別限定,例如用戶端的作業環境是 Windows 2000 + IIS,而執行 Web Services 的作業環境是 Linux + Apache。要符合這些條件,就一定要有一套標準的協定才行,這個標準協定就是 Simple Object Access Protocol(SOAP)。
SOAP 是架構在 HTTP 之上的物件存取協定,也就是說透過 HTTP 來傳遞訊息,而訊息的內容則是以 XML 格式來描述。當用戶端程式需要呼叫一個遠端物件的方法時,可以把這項要求封裝成 SOAP 呼叫傳遞給遠端的 Web Services,當 Web Services 收到了用戶端的請求便去執行其指定的方法,並且在執行完畢之後傳回結果。因此也可以說 SOAP 就是 internet 上面的 RPC。
相較於傳統的 RPC,SOAP 不但是個被業界所支援的公開標準,還具有容易穿透防火牆的優點,使遠端程序呼叫得以順利跨越不同的網域。SOAP 之可以順利穿透防火牆,是由於其搭載的純文字訊息是透過 HTTP 協定來傳輸,而大部分的企業網路的防火牆都會開放 HTTP 使用的 80 埠的緣故。
WSDL
當你在網路上找到一個 Web Service,你如何知道要怎樣使用它?它提供了什麼服務?有哪些方法可以呼叫?要傳遞哪些參數?這些問題的答案就是 WSDL(Web Service Description Language)。
WSDL 是一份以 XML 撰寫的文件,附檔名就是 .WSDL,其主要的用途是「描述 Web Services」,也就是讓用戶端知道如何使用 Web Services。WSDL 的文件內容也有一個共同的標準,以便與各種用戶端應用程式相互整合,此標準是由 IBM 與 Microsoft 共同研擬。
如果你瞭解 COM 的話,WSDL 的作用就等同於 COM 的 IDL(Interface Difinition Language)或 type library。
Web Service Discovery(又稱為 Disco)
WSDL 是在你已經確定要使用某個 Web Service 並且知道其網址的情形下才有用,萬一你不知道哪裡有你需要的 Web Services 怎麼辦?例如,你的應用程式現在要加入一項功能,可以讓使用者輸入特定關鍵字找尋相關的 MP3 檔案的下載網址,這時候你要去哪裡找這類 Web Services?
Disco 的用途就在這裡,就像電話簿和搜尋引擎網站一樣,提供資訊分類以及尋找的服務,讓你可以方便快速地找到你需要的 Web Services。
其運作原理是,當開發人員將一個 Web Service 設計完成之後,可以將它登錄到一個集中的地方,其他人就可以向這個集中地查詢找到需要的服務。這個登錄-查詢的機制只要就是依靠 UDDI(Universal Description, Discovery and Integration)來達成。
Web Services 的架構
將 XML,SOAP,WSDL,UDDI 這些核心元素組合起來,就可以形成一個 Web Services 架構,架構中包含了三種主要的角色,分別是 Web Services 的提供者(provider),消費者(consumer),與介於兩者之間的中介者(broker),參考下圖:
其運作流程如下:
服務提供者開發 Web Services。
服務提供者將 Web Services 佈署至伺服器環境,並且向服務中介者登錄其相關資訊至 UDDI 註冊資料庫中。
服務的消費者到 UDDI 註冊資料庫中搜尋所需的服務。
服務的消費者在取得 Web Services 的相關資訊後就可以使用該服務。
可能面臨的挑戰
面對一項新的技術,在瞭解它的優點及學習如何應用該項技術的同時,也必須注意可能伴隨該項技術而來的問題,以免將技術用錯了地方或者太晚發現決策的錯誤。因此這裡摘要地列出一些應用 Web Services 時可能遭遇的挑戰以玆參考,內容摘自 Graham Glass 的文章「The Web services (r)evolution, Part 1」。
可靠性
如果原本提供 Web Services 的伺服器掛掉了,用戶端該如何應變?是否可能以其他廠商提供的 Web Services 暫時替代?這個替代品的功能和使用方式是否跟原本的 Web Services 完全相同?
安全性
在網路上傳遞敏感資料時需要將資料加密處理,HTTP 配合 SSL 可以提供基礎的安全防護,但是對一些需要對個人身分進行驗證與授權的場合就不夠用了,此時 Web Services 要做到什麼程度才算安全?是否需要在每個方法呼叫中傳遞及驗證使用者的身分?效率與安全的平衡點在哪裡?
交易處理
以往的分散式應用程式使用兩段式交付(two-phase commit)的方式完成分散式交易,這種方式在企業內部網路的環境下處理短時間的交易沒有什麼問題,但是如果拿到網際網路的開放環境下就窒礙難行了,因為一個交易啟動之後,也許要經過數天之後交易才完成,啟動交易的作業是否要一直等待直到所有參與交易的作業都成功後才確認完成整個交易?實際上不可能這樣做。因此 Web Services 在分散式交易的處理上目前仍有待努力,目前 Microsoft 提出了補償交易的方案(XLANG),而 W3C 則尚未針對此問題制定相關的標準。
經營模式
你的 Web Services 要如何收費?收取年費還是用多少算多少?你如何預防用戶將帳號密碼告訴其他人以共享存取你的 Web Services?
除錯
由於每個用戶端所執行的作業系統及環境可能不同,因此如何確保你的 Web Services 可以適用各種用戶端的環境也是可能碰到的問題,當用戶端向你回報錯誤訊息的時候,你是否能在限定的時間內解決問題?需要模擬用戶的作業環境嗎?
牛刀小試
在了解一些基礎概念之後,讓我們來試著練習撰寫一個簡單的範例程式。以往介紹分散式應用程式的撰寫步驟時,通常會先建立伺服器端的程式,然後再建立用戶端程式,這是因為用戶端所需的特定功能往往都沒有現成的,而必須自行撰寫的緣故。所幸 internet 上面已經有不少現成的 Web Services,我們便可以先學習撰寫難度較低的用戶端程式,知道如何使用之後再學習如何撰寫 Web Services。
首先選定要使用的 Web Service,http://www.xmethods.com 上面有不少現成的,我打算用一個叫做 Email Address Verifier 的 Web Service 來做示範,它提供了驗證 MSN、Hotmail、以及 Yahoo 等免費的電子郵件信箱是否有效的服務。這個 Web Service 是以 VisualStudio.NET 開發出來的,這裡我分別以 Delphi 6 和 VisualStudio.NET 7 英文版來說明開發 Web Service 用戶端程式的步驟,您可以看看兩種工具的程式撰寫方式有何異同。
以 Delphi 6 撰寫用戶端程式
建立一個新的應用程式:File|New|Applicatoin,接著先存檔。
透過 WSDL Importer 將指定的 Web Service 介面轉成 Delphi 的介面:
File|New|Other...,選擇 WebServices 頁夾的 WSDL Importer,然後按 Ok 鈕。在接下來開啟的 WSDL 匯入精靈視窗中輸入 Email Address Verifier 的 WSDL 的 URL:http://ws.cdyne.com/emailverify/ev.asmx?wsdl,完成後會產生一個新的單元 ev.pas,其中繼承自 IInvokable 的 evSoap 介面就是我們要用來呼叫遠端物件的介面。
下列元件各放一個到 Form1 上面:THTTPRIO,TEdit,TButton,TMemo。其中 TMemo 是用來顯示驗證 email 信箱的結果。然後按 Alt+F11,use ev 這個單元。
設定 HTTPRIO1 的屬性,如下:
object HTTPRIO1: THTTPRIO
WSDLLocation = 'http://ws.cdyne.com/emailverify/ev.asmx?wsdl'
Service = 'ev'
Port = 'evSoap'
Converter.Options = [soSendMultiRefObj, soTryAllSchema, soRootRefNodesToBody]
end
註:由於 Email Address Verifier 是 .NET 應用程式,所以使用 WSDLLocation 屬性,而以 Delphi 開發的 Web Services 則可以使用 URL 屬性。
撰寫 Button1 的 OnClick 事件:
procedure TForm1.Button1Click(Sender: TObject);
var
intfEV: evSoap;
ri: ReturnIndicator;
begin
Screen.Cursor := crHourGlass;
Application.ProcessMessages;
try
intfEV := HTTPRIO1 as evSoap;
ri := intfEV.VerifyEmail(Edit1.Text);
Memo1.Clear;
Memo1.Lines.Add('ResponseText: ' + ri.ResponseText);
Memo1.Lines.Add('ResponseCode: ' + IntToStr(ri.ResponseCode));
finally
intfEV := nil;
Screen.Cursor := crDefault;
end;
end;
編譯並且執行。執行時先在 Edit1 中輸入一個你自己的 MSN 或 Yahoo 的免費 email 信箱,然後按 Button1,看看 Memo1 裡面顯示的驗證結果。
如果 Memo1 裡面顯示的驗證結果是 "Verified Email Address" 或 "Mail Server Accepted Email",就表示你輸入的電子郵件信箱是有效的,這時候你可以開啟電子郵件軟體收信看看,應該會有一封由 www.email-tester.com 寄來的通知信,原來背後真正提供驗證服務的是這個網站。如果你在上個步驟輸入的是別人的郵件信箱,收到信件的自然就是別人了。
執行結果參考下圖:
以 VisualStudio.NET 撰寫用戶端程式
我以 C# 來撰寫,步驟如下:
點選主選單的 File | New | Project,在接著開啟的 "New Project" 對話窗中,"Project Type" 選擇 "Visual C# Projects","Templates" 選擇 Windows Application,"Name" 輸入 "EmailVerifyClient",然後按 Ok 鈕。參考下圖:
點選主選單的 Project | Add Web Reference,在接著開啟的視窗裡,欄位 Address 要輸入 Web Service 的 URL,這裡我們直接輸入 Email Address Verifier 的 WSDL 位址:http://ws.cdyne.com/emailverify/ev.asmx?wsdl,然後按 Enter 鍵。如果有找到這個 Web Service 的話就會顯示在下方面板裡面,此時按 Add Reference 鈕就可以加入 Web 參考,也就是幫你產生這個 Web Service 的 proxy 類別,操作畫面如下圖所示:
產生的 proxy 類別名稱是 "ev",你可以在 Class View 視窗裡找到並且叫出這個類別的程式碼。
在 Form1 上面放兩個 TextBox,一個 Button。在 Form1.cs 中加入下列程式碼:
using EmailVerifyClient.com.cdyne.ws;
在 button1 的 Click 事件中撰寫程式碼,如下:
private void button1_Click(object sender, System.EventArgs e)
{
ev oEV;
ReturnIndicator ri;
oEV = new ev();
ri = oEV.VerifyEmail(textBox1.Text);
textBox2.Text = ri.ResponseText;
}
編譯並執行,先在 textBox1 中輸入 MSN 或 Yahoo 電子郵件信箱,然後按 button1,驗證結果會顯示於 textBox2。執行畫面參考下圖:
以上兩種開發工具的程式撰寫方式其實是大同小異的,值得注意的是兩者都能夠自動產生 Web Service 的 proxy 類別,讓程式設計師在撰寫用戶端程式時可以透過這個 proxy 類別來存取 Web service 元件所提供的服務。
範例程式下載
EvClient_D6.zip (for Delphi 6)
EvClient_VS.zip (for VS.NET)
結語
拜 internet 之賜,在全球化經濟之後,軟體產業也將逐漸感受到全球化的壓力,而不得不加入世界的脈動了。Web Services 的出現,提供了另一種應用程式之間的溝通方式,範圍更廣(遍及全球),支援的平台也更多,也許它真能創造出另一種新興的軟體服務業,屆時全球各地將有各式各樣的軟體服務,琳瑯滿目任君挑選,而且軟體開發人員再也不用侷限於一種開發工具或程式語言了。Web Services 是否提供足夠的條件達成這個願景?且讓我們拭目以待吧。
這次除了介紹 Web Services 的一些基礎觀念,也用一個相當陽春的範例展示如何以 Delphi 6 及 VisualStudio.NET 開發 Web Services 用戶端程式,下次有機會再進一步介紹 Web Services 程式設計的相關議題。
參考資料
Myths and misunderstandings surrounding SOAP by Frank Cohen。
網址:http://www-106.ibm.com/developerworks/webservices/library/ws-spmyths.html
The Web services (r)evolution, Part 1 by Graham Glass。
網址:http://www-106.ibm.com/developerworks/webservices/library/ws-peer1.html
Introducing .NET by Conard, Dengler, Francis, Glynn, Harvey, Hollis, Ramachandran, Schenken, Short, Ullman. Wrox Press 2000.