Delphi 6 Web Services初步評估

vsaber發表於2002-02-08

Delphi 6 Web Services初步評估<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

這是我剛到現在公司的時候(2001年8月份)所作的一份測試報告,現公佈出來,希望能對大家有所幫助。因為當時d6剛剛發行,Web Service方面還存在一些問題,當前的update 1 for D6已經發布,主要就針對Web Service做了大量的修改,已經能與MS相關的Web Service相容了。可能下面文章內提到的部分內容在Update1有所變動,在此說明!

2000622日,整個IT行業期盼著一個令人嚮往的新時代,因為今天美國微軟公司正式對外宣佈了.Net戰略,並且確定每年為這個新的戰略投入40億美元的研發費用。.Net的思想徹底地把計算模式從單機、客戶機/伺服器和Web網站的方式轉向分散式計算(Distributed Computing)。雖然DCOM和Corba是當今比較流行的分散式物件模型,然而它們都存在著僅能用於本地網路這個侷限性,很難突破防火牆的限制,因此不能把整個網際網路作為一個計算資源體系加以利用。.Net則通過一種稱為Web Services的技術把分佈在網際網路上的各種資源有效的通過程式設計手段整合在特定的應用介面裡。

作為.Net的核心概念,Web Services是目前炙手可熱的技術,各大廠商,如Microsoft、IBM、SUN等莫不投入大量的資源以求站在領導地位。Borland公司於2001年6月份釋出的最新的RAD工具Delphi 6.0,並且把支援Web Service開發作為最大的賣點。近日,我對Delphi6建立Web Services程式進行了初步的測試和評估。

 

一、       Web Service概述:

Web Services就相當於過去我們程式設計中常常呼叫的API函式和在物件導向程式設計中呼叫

的介面,只不過API存在於本機上,介面通常存在於本機或者本地區域網內,而Web Services則將無所不在地分佈在整個網際網路絡上。

Web Services可以真正的實現跨平臺遠端過程呼叫RPC(Remote Process Call),無論採用何種作業系統,無論採用何種構架的硬體,無論採用什麼語言呼叫,都能夠處理它的呼叫請求。因為Web Services是由SOAPSimple Object Access Protocol)作為封裝協議,HTTPHypertext Transfer Protocol)作為通訊協議組成,並且通過WSDLWeb Services Discription Language)描述服務介面等資訊。

SOAP,定義了客戶端呼叫伺服器端介面方法的一種機制。由於SOAP是基於擴充套件標記語言XMLExtensible Markup Language)標準文件方式,因此它可以輕鬆的實現跨平臺,它使用XML定義了一套編碼規則,用於網路上傳輸呼叫請求資訊以及迴應資訊。

HTTP,作為WWW(World Wide Web)所使用的通訊協議,因為防火牆對各個埠進行監控,而HTTP使用的80埠用於Internet訪問,通常防火牆不會限制此埠通訊,所以一般可以通過防火牆,與連線在網際網路上的機器通訊。

WSDL,用於描述當前Web Service的各種資訊,以便與客戶端通過WSDL來取得呼叫介面的資訊。

 

 

二、       評估測試過程:

整個評測的目標是驗證Delphi 6對建立Web Services工程的支援程度,Web

Services的工作效率,以及與其它廠商Web Services的整合相容性。

   

測試環境:

CPU:PIII 550

記憶體: 256MB

OS: Windows2000 Server + SP2

Web Server:IIS 5.0 + SP3

開發環境:Borland Delphi 6.0 <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />Enterprise

          Microsoft Visual Studio 7.0 Beta 2

          Microsoft SOAP TOOLKIT 2.0

 

基本測試過程:

Web Services通過介面方法呼叫返回值來獲取呼叫結果,因此測試程式通過呼叫不同型別返回值的介面方法來作為測試方向,分為以下四種:字串型別返回值,物件型別返回值,物件陣列型別返回值和二進位制檔案返回值。

 

1、  TEST1(字串型別返回值方法呼叫):

首先採用Delphi 6建立一個Web Services工程,Delphi 6通過嚮導自動生成一個單元,此單元包括了Web Services通訊所需要的各個控制元件:THTTPSoapDispatcher用於響應基於SOAP的請求,並轉交給其它的處理控制元件;HTTPSoapPascalInvoker用於從THTTPSoapDispatcher接收SOAP訊息,並進行分析呼叫合適的介面方法,最後對介面呼叫返回結果進行封裝(Encode);TWSDLHTMLPublish則是用於公佈描述此Web Service介面的WSDL文件。

要為Web Service服務提供介面方法,需要建立一個從IInvokable繼承的介面,以及從TInvokable繼承的實現此介面的物件。

下面,我們就可以為這個Web Service新增方法了。在這第一個評估測試中,我們需要新增一個字串型別作為返回值的方法,而且為了儘量準確的測試響應效率,我們希望能傳輸比較大資料量的字串。因此建立了一個1024個‘Hello, The World!’組合的字串作為方法的返回值。

呼叫結果如圖一所示:

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

(圖一)

客戶端的呼叫,順利取得了伺服器端的字串並顯示出來。畢竟伺服器對返回值的編碼也是文字型別,所以說碼耗費的時間並不多,因此整個請求的效率還是可以讓人滿意的。

當然,正是因為Web Services是基於SOAP的,傳遞文字自然是“拿手好戲”,但在    我們實際應用中,需要的結果通常來說不是字串文字,而是別的資訊,為了繼續

證明Web Services將會帶給我們的驚喜,我進行了下一個測試。

 

2、  TEST2(物件型別返回值方法呼叫):

在實際應用中我們常常會遇到客戶端需要的是從伺服器端返回資料庫查詢結果,在這種情況下,返回的資料可能是各種型別資料的組合,這個測試將會告訴我們如何通過Web Services傳遞複雜型別資料資訊。

傳遞的複雜型別資料資訊可以通過物件進行封裝,便於建立於使用中的管理,更重要的是因為Delphi“強迫”我們不得不這樣做。在Delphi 6中,如果介面返回值為物件,則此物件必須是從Tremotable類繼承下來,並且對客戶端能訪問的成員變數必須作為屬性公佈。

針對測試,我建立了一個從Tremotable繼承的類TXSPerson,並且公佈了六個屬性:ID、Name、Age、Gender、Content、Email。因此我可以在客戶端通過方法訪問這個類例項的這六個成員變數的值。在伺服器端,我分別對這六個值進行了賦值,並把類作為方法的返回值。客戶端的呼叫此方法得到TXSPerson型別的物件例項,從而訪問它的屬性值。

呼叫結果如圖二所示:

(圖二)

從上面的結果可以看出,傳輸物件的效率就沒有傳輸字串高了。首先一點,在伺服器端程式和客戶端程式都必須管理一個類,相對於傳遞字串多了這些類的管理開銷,自然影響了效率。

從這個測試中,我們可以傳遞複雜型別的資料了,對於絕大多數的實際應用來說,每次傳遞已比資料是不夠的,我們可能需要的是大量的資料庫記錄傳遞。在Web Services中,可以通過使用動態陣列來實現,正如下一個測試。

 

3、  TEST3(物件陣列型別返回值方法呼叫):

當伺服器端的一大筆資料庫記錄需要傳遞給客戶端,每一條記錄作為一個物件例項儲存,所有的記錄用一個物件陣列儲存,並且以物件陣列作為返回值傳遞到客戶端。在這個測試中,我採用了與資料庫結合的方式進行測試,以便於去更真實的模擬實際的應用。資料庫我採用了Access2000,通過ADOMicrosoft ActiveX Data Objects)進行連線訪問,並建立一個動態陣列儲存查詢的各個欄位的結果,作為返回值返回到客戶端。

呼叫結果如圖三所示:

(圖三)

可以看出來,呼叫仍然非常順利,客戶端獲得了期望的資料紀錄。但是相對於傳輸一條記錄來說,效率再一次的降低了。應該說來是因為動態陣列的原因導致了效率的降低,動態陣列是Delphi的一個特徵,在C/C++中是沒有動態陣列的,所以C/C++中陣列的記憶體都是在編譯期間分配的。而Delphi中引入了動態陣列,這使得只能在執行期間動態的分配記憶體,從而導致了對動態陣列管理所引起的開銷,影響效率。

在實際應用中,有時候我們需要傳遞檔案,例如說資料庫裡面的圖片,通過Web Services應該怎麼實現呢?作為一種簡單的解決辦法,我們再一次求助於動態陣列。

 

4、  TEST4(二進位制檔案返回值方法呼叫):

在最後一個返回值型別測試中,為了測試Web Services對檔案的傳輸能力,我通過方法結果傳遞一個JPEG的圖片。要使客戶端能接收到伺服器端的圖片,必須採用某種標準返回值型別來組織圖片的內容,在測試中使用了動態陣列TbyteDnyArray作為返回型別。

伺服器端通過TfileStream讀取出圖片檔案的內容,並拷貝到TbyteDnyArray陣列中,客戶端接收到TbyteDnyArray型別的陣列後使用TmemoryStream寫回到檔案中去,從而完成了檔案的傳輸過程。

呼叫結果如圖四所示:

(圖四)

功能的確實現了,但是測試的結果卻讓人大吃一驚,雖然也猜想到,採用如此“巨大”的動態陣列會對效率產生比較大的影響,事實也的的確確也證明了,這種方式實現檔案傳輸的方法是不可行的。

毫無疑問,如此低下的效率正是因為動態陣列的開銷所導致,對於15KB的圖片來說,動態陣列將為它的每一個位元組生成一個元素,系統的記憶體管理終究也顯得如此“捉襟見肘”。

雖然採用這種方法傳遞檔案我們“失敗”了,但是並不是說明沒有高效率的傳遞檔案的辦法。作為二進位制的檔案,如果要作為Web Services的返回結果傳遞在網路上,就必須把二進位制檔案存放在SOAP資訊中,SOAP卻是文字檔案,所以對於二進位制檔案作為文字檔案再網上傳輸,完全可以採用已經成熟的協議了,最常用的莫過於MIMEMultipurpose Internet Mail Extension protocol)了。通過Base64編碼或其他方式對圖片進行編碼以後,傳遞到客戶端以後,在進行Base64的解碼,效率將會數十倍的提高。但是因為Delphi 6雖然提供了Base64編碼解碼,但是因為一些不完善的原因使我放棄了對這個方法的測試。

   

   

    測試總體印象:

在整個測試中,對Delphi 6建立的Web Services有以下幾個印象:

 

1、  客戶端應用程式連線伺服器端Web Service的時候,第一次呼叫很慢,而以後的呼叫明顯加快。

五顯示了呼叫各個介面第一次和第二次的傳輸速率(每秒鐘傳輸千位元組數KB/S)。

由此可以看出,第一次的方法呼叫非常耗時,可能達到第二次呼叫的8倍,因此可以確定,第一次呼叫介面的時候,大量的操作事件耗費在連線的建立上面。一旦連線建立,以後的呼叫速度會大大加快。

(圖五)

從圖五中,也能明顯的看到各種不同返回型別測試的效率高低。

 

2、  拋開第一次方法呼叫耗時以外,某些方法每次呼叫測試資料傳輸速率不穩定。例如測試TEST1和TEST2中,基本上速率為850KB/S或者1134KB/S,而TEST3的傳輸速率變化則非常廣,從401KB/S到530KB/S都隨機出現,而TEST4的測試因為速率太小,可能導致比較大的誤差,在此不做考慮。

TEST1、TEST2相對測試比較穩定,是因為伺服器端是直接返回了所需要的值,速率的變化僅僅來至於傳輸過程。而TEST3中必須從資料庫中讀出資料,並且建立了動態陣列來傳遞資料,因此出現速率影響因素較多,導致傳輸速率變化比較大。

 

 

    Web Services相容性問題測試:

正是由於Web Services的火熱,導致各家大廠商聞風而動,並且推出自己相關的概念,建立自己的方案。例如SUN公司推出ONE (Open Net Environment)的概念對抗微軟,Oracle公司則以Dynamic Web Service的概念表示與微軟抗衡。

SOAP的規格在不斷的發展,從0.9、1.0到現在的1.1。但是,目前市面上提供SOAP功能的軟體並不一定都符合最新的SOAP規範,即使是支援相同SOAP版本規格的軟體,對於如何實現可能都有一些差異。但是,可能正是由於這一些細微的差異可能造成軟體開發人員的困擾,更何況Web Services是以SOAP為基礎的溝通技術。因此,如果不同SOAP軟體介面對於SOAP規格的實現有所不同,將會造成客戶端應用程式無法和Web Service溝通,或是在Web Service和Web Service之間無法使用彼此提供的服務。這樣將會失去SOAP和Web Services技術的精髓。

 

下面的測試採用了當前最流行的兩個平臺進行相容性測試,Microsoft Visual Studio 7 Beta 2版本,和剛剛發行的Delphi 6 Enterprise。

在前面的測試中,我採用Delphi 6建立Web Services,並用Delphi 6開發客戶端進行連線,整個過程非常完美。然而現在,我們的測試一下是否當前最火的兩個開發工具能“和平共處”呢?

首先,我在VS7環境下面,使用C#建立了一個Web Services,提供一個方法AddXY( int x, int y);然而當我在Delphi中呼叫的時候,很讓人失望,出現瞭如圖六的呼叫錯誤:

(圖六)

 

看來,VS7和Delphi6還不能很好的合作到一起。當使用MST2Microsoft Soap Toolkit 2.0)帶的追蹤工具Trace Utility攔截HTTP資訊,察看傳遞的SOAP資訊。發現VS7開發的Web Services的SOAP和Delphi6開發的Web Services的SOAP有一些不一樣。正是因為這些格式的不一樣,導致了它們之間溝通的失敗。

而且不但SOAP格式不太一樣,連WSDL的格式都大相徑庭,以至於Delphi 6匯入剛才我們在VS7下寫的方法public int AddXY(int x, int y)以後,生成的介面宣告如下:procedure AddXY(var parameters: AddXY);  stdcall;因此產生了很讓Delphi自己“尷尬”的事情,這是一個procedure而不是function,呼叫這個方法沒有返回值,也就是得不到方法呼叫的結果,雖然生成的介面方法中引數parameters為AddXY類,並且是一個var型別的引數,可惜,很遺憾,客戶端所需要的結果並沒有包含在AddXY類中。而Delphi為這個方法宣告瞭一個結果類AddXYResponse,可是我們卻無法通過呼叫方法得到這個物件例項。通過進一步對介面描述檔案WSDL的分析,發現Delphi 6對WSDL檔案的解釋存在某些BUG,導致了生成介面宣告出現錯誤的問題。

總的來說,當前Microsoft和Borland之間的Web Services方案看來還是存在著很大的不同點。但是這並不是說我們就不能在delphi下面呼叫VS7建立的Web Services方法。我們還是可以通過MST2提供的COM介面進行訪問。通過我的測試,這種方法沒有問題,能夠順利的呼叫VS7的Web Services的各個方法,畢竟MST2和VS7 Beta2都是微軟的產品。

當然,它們之間的不相容,讓我們很傷腦筋,作為當前的兩大主流開發環境,竟然不能讓我們體驗到Web Services跨平臺、跨語言的優越性,實在讓人有些失望。

畢竟SOAP和Web Services標準以及技術仍然處於快速的發展之中,因此目前各家實現的細節可能會稍有不同,也許等到SOAP功能規格成熟之後,就不會再有這些惱人的細節問題。據資料介紹,Delphi 6的Web Services是能夠順利的整合到許多由Java實現的Web Services或是Java客戶端應用程式,看來,Borland Delphi 6的Web Services實現還是偏向於IBM的陣營!

 

    建立Web Services的技巧:

1、  IIS 5中的相關設定:

因為Delphi 6建立的Web Services是一個ISAPI(Internet Server Application Programming Interface)程式,所以必須使用IIS作為它的伺服器。在實際的開發和應用中,應該注意一下關於IIS5中針對ISAPI的快取設定問題。

啟動Internet服務管理器,選擇Web站點的“屬性”,依次選擇彈出對話方塊的“主目錄-〉配置”將會彈出如圖七所示的對話方塊。

              

(圖七)

Web Service伺服器端程式設計期間,因為需要不停的修改、編譯和測試程式執行,所以不能使用“快取ISAPI應用程式”,否則一旦執行程式,伺服器程式就會總是處於使用期間,重新編譯的新程式無法覆蓋。

而一旦伺服器端程式完成以後,則最好選擇“快取ISAPI應用程式”,因為一旦執行ISAPI程式它會被調入快取以後,在以後的執行中效率會大大提高,據測試,至少有一倍以上的提升幅度。

 

2、  Delphi 6建立Web Services工程的除錯方法:

作為一個執行於IIS下的ISAPI應用程式,Delphi建立的Web Services是一個DLL動態庫,所以除錯方法和一般的應用程式不太一樣:

在建立Web Services程式的嚮導中,應該選擇Web App Debugger excutable程式,建立出來的將會是一個可執行程式。然後使用Delphi 6自帶的“Web App Debugger”除錯工具作為Web Sever,並設定對應的埠,這時候就可以在Delphi的IDE下面除錯伺服器程式了。

當程式除錯執行正常以後,需要作為ISAPI釋出,只需要重新建立一個Web Sercices ISAPI程式,並把除錯程式下的相關檔案全部加入到新工程就可以了。

 

三、       總結:

在以上的測試中已經證明了,Web Services能傳遞各種各樣的資料形式,由於Delphi已經為它封裝了底層類進行傳輸複雜型別資料,因此,用Delphi6開發Web Services也比較簡單。當前面臨的主要問題就在於與Microsoft之間的整合問題,Delphi 6對微軟WSDL的解釋出現錯誤,和一些其它的相互之間差異,導致它們之間無法相互呼叫。雖然可以在Delphi 6中使用MST2進行呼叫,但是這就等於拋棄了Delphi 6自身的Web Services支援。

 

在整個測試過程中,我主要注重了Web Services實用性方面的測試,Web Services雖

然在傳輸效率穩定性上都還不是特別的理想,但是畢竟微軟的.Net戰略是一個對現在來說超前的概念,它的真正成熟必須依靠與寬頻網路的普及,才能讓使用者體驗到Web Services的優越性。

 

當前,國內對Web Services的研究才剛剛起步,各大論壇才新近推出相關的討論版,而且相對比較冷清。作為今後軟體技術的核心概念,Web Services的火熱程度將會有增無減。

 

隨著各軟體廠商參與Web Services研發的積極性,正促使著Web Services的迅速發展,以及相關協議的確定。隨著外部環境的日趨成熟和自身的完善,Web Services必然作為全新的軟體開發理念席捲整個行業。正如微軟所說:“Empower people through great software -- any time, any place and on any device.”(先進的軟體讓人們隨時,隨地,通過任何裝置獲得強大能量

 

 

 

 

 

 

 

 

 

 

 

 

 

參考資料:

《肥皂的戰爭與和平》----- 李維

.Net:解讀微軟網際網路新戰略》-----毛向輝 陳志紅

Borland Delphi 6 Help》

Borland Delphi 6 for Windows Develper’s Guide》

……

相關文章