|
SOAP(Simple Object Access Protocal) 技術有助于實現(xiàn)大量異構程序和平臺之間的互操作性,從而使存在的應用能夠被廣泛的用戶所訪問。SOAP是把成熟的基于HTTP的WEB技術與XML的靈活性和可擴展性組合在了一起。 這篇文章帶你全面回顧對象遠程進程調用(ORPC)技術的歷程,以幫助你理解SOAP技術的基礎,以及它克服存在技術(如CORBA和DCOM)的許多缺陷的方法。隨后講述詳細的SOAP編碼規(guī)則,并把焦點放在SOAP是怎樣映射到存在的ORPC概念上的。 引言: 當我在1984年開始把計算作為我的職業(yè)的時候,大多數(shù)程序員并不關心網(wǎng)絡協(xié)議。但是在九十年代網(wǎng)絡變得無所不在,現(xiàn)在如果有誰使用計算機卻不使用某種形式網(wǎng)絡連接是很難以想象的。今天,一般的程序員對建立可擴展的分布式應用表現(xiàn)出更大的興趣,而不再只是關注于用MFC實現(xiàn)個性化的可浮動半透明非矩形的Coolbars了。 程序員通常喜歡用編程模型來思考問題,而很少考慮網(wǎng)絡協(xié)議。盡管這樣做通常是很好的,但在這篇文章中我將討論的SOAP是一個沒有明顯的編程模型的網(wǎng)絡協(xié)議。這并不意味著SOAP的體系結構從根本上會改變你編程的方式。相反,SOAP的一個主要目標是使存在的應用能被更廣泛的用戶所使用。為了實現(xiàn)這個目的,沒有任何SOAP API或SOAP 對象請求代理(SOAP ORB),SOAP是假設你將使用盡可能多的存在的技術。幾個主要的CORBA廠商已經(jīng)承諾在他們的ORB產(chǎn)品中支持SOAP協(xié)議。微軟也承諾在將來的COM版本中支持SOAP。 DevelopMentor已經(jīng)開發(fā)了參考實現(xiàn),它使得在任何平臺上的任何Java或Perl程序員都可以使用SOAP。 在SOAP后面的指導理念是“它是第一個沒有發(fā)明任何新技術的技術”。SOAP采用了已經(jīng)廣泛使用的兩個協(xié)議:HTTP和XML。HTTP用于實現(xiàn)SOAP的RPC風格的傳輸,而XML是它的編碼模式。采用幾行代碼和一個XML解析器,HTTP服務器(如MS的IIS或Apache)立刻成為了SOAP的ORBs。 因為目前超過一半的Web服務器采用IIS或Apache, SOAP將會從這兩個產(chǎn)品的廣泛而可靠的使用中獲取利益。這并不意味著所有的SOAP請求必須通過Web服務器來路由,傳統(tǒng)的Web 服務器只是分派SOAP請求的一種方式。因此Web服務如IIS或Apache對建立SOAP使能的應用是充分的,但決不是必要的。 正如這篇文章將要描述的,SOAP簡單地用XML來編碼HTTP的傳輸內容。SOAP最常用的應用是作為一個RPC協(xié)議。為了理解SOAP怎樣工作,有必要簡要回顧一下RPC協(xié)議的歷史。 RPCs的歷史 建立分布式應用的兩個主要通信模型是消息傳送(經(jīng)常與隊列組合在一起)和請求/響應。消息傳遞系統(tǒng)允許通信任何一方在任何時間發(fā)送消息。請求/響應協(xié)議把通信模式限制在請求/響應的雙方。基于消息的應用強烈地意識到它們正在與外部的并行進程進行通信,并且需要一個顯式的設計風格?;谡埱?響應的應用更象一個單進程的應用,因為發(fā)送請求的應用或多或少被阻塞直至收到來自另一個進程的響應。這使得請求/響應通信自然地適合于RPC應用。 盡管消息通信和請求/響應各有他們的優(yōu)點,他們都是可以用對方來實現(xiàn)的。消息系統(tǒng)可以用較底層的請求/響應協(xié)議來建立。如微軟的Message Queue Server (MSMQ)內部采用了DCE RPC來建立大多數(shù)的控制邏輯。RPC系統(tǒng)也可以采用較底層的消息系統(tǒng)來建立。MSMQ提供的關聯(lián) ID正是為了這個目的。不管評價如何,大多數(shù)的應用仍趨向于使用RPC協(xié)議,因為它們廣泛的使用,它們更簡單的設計,以及更自然的到傳統(tǒng)的編程技術的映射。 在八十年代,兩個主要的RPC協(xié)議是Sun RPC 和DCE RPC。最流行的Sun RPC應用是大多數(shù)UNIX系統(tǒng)所使用的Network File System (NFS)。最流行的DCE RPC應用則是Windows NT?,它采用DCE RPC 協(xié)議來實現(xiàn)許多系統(tǒng)服務。這兩個協(xié)議被證明適用于很大范圍的應用。但是,在八十年代末期,面向對象技術的風靡使軟件界沉迷于在面向對象語言和基于RPC的通信之間建立一個紐帶。 在九十年代產(chǎn)生的對象RPC (ORPC) 協(xié)議正是試圖把面向對象和網(wǎng)絡協(xié)議聯(lián)系起來。ORPC 和 RPC 協(xié)議的主要不同是ORPC代碼化了從通信終端到語言級對象的映射。在每個ORPC請求的頭中都有一個cookie,服務器端的程序能用它來定位在服務器進程中的目標對象。通常這個cookie只是一個對數(shù)組的索引,但其它技術也經(jīng)常被使用,如用符號名作為Hash表的鍵。 目前兩個主要的OPRC協(xié)議是DCOM 和 CORBA的 Internet Inter-ORB Protocol (IIOP) 或更一般的General Inter-ORB Protocol (GIOP)。DCOM和IIOP/GIOP的請求格式非常相似。兩個協(xié)議都用一個對象端點ID來確定目標對象,用方法標識符來決定調用哪個方法。 這兩個協(xié)議主要有兩點不同:主要的一點不同是采用IIOP/GIOP時,接口標識符是隱含的,因為一個給定的CORBA對象只實現(xiàn)一個接口(盡管OMG當前正在進行每個對象有多個接口支持的標準化工作)。DCOM與IIOP/GIOP請求的另一個細微差別是在傳輸體中參數(shù)值的格式。在DCOM中,傳輸體用網(wǎng)絡數(shù)據(jù)表達(NDR)的格式來寫,在IIOP/GIOP中,傳輸體用公共數(shù)據(jù)表達(CDR)的格式來寫。NDR和 CDR分別處理在各種平臺上的不同的數(shù)據(jù)表達。但是在這兩種格式之間有一些小的差別,這使它們相互之間并不兼容。 在ORPC與RPC協(xié)議之間的另一個重要的不同是通信端點的命名方式。在ORPC協(xié)議中,對于ORPC端點的一些可傳遞的表達方式被要求在網(wǎng)絡之間傳遞對象引用。在CORBA/IIOP,這個表達方式被稱為可交互的對象引用(IOR)。IORs包含用緊湊格式表達的尋址信息,使用了它任何CORBA產(chǎn)品都可以決定一個對象端點。在DCOM中,這種表達方式被稱為OBJREF,它組合了分布的引用計算和端點/對象標識。CORBA和DCOM都提供了在網(wǎng)絡上尋找對象端點的高級機制,但最終這些機制都映射回到了IORs或OBJREFs。 目前的技術存在的問題? 盡管DCOM和IIOP都是固定的協(xié)議,業(yè)界還沒有完全轉向其中任何一個協(xié)議。沒有融合的部分原因是文化的問題所致。而且在當一些組織試圖標準化一個或另一個協(xié)議的時候,兩個協(xié)議的技術適用性就被提出質疑。傳統(tǒng)上認為DCOM和CORBA都是合理服務器到服務器端的通信協(xié)議。但是,二者對客戶到服務器端的通信都存在明顯的弱點,尤其是客戶機被散布在Internet上的時候。 DCOM 和 CORBA/IIOP都是依賴于單個廠商的解決方案來最大優(yōu)勢地使用協(xié)議。盡管兩個協(xié)議都在各種平臺和產(chǎn)品上被實現(xiàn)了,但現(xiàn)實是選定的發(fā)布需要采用單一廠商的實現(xiàn)。在DCOM的情況下,這意味著每個機器要運行在Windows NT。(盡管DCOM已經(jīng)被轉移到其它平臺,但它只在Windows?上獲得了廣泛的延伸)。在CORBA情況下,這意味著每個機器要運行同樣的ORB產(chǎn)品。的確讓兩個CORBA產(chǎn)品用IIOP相互調用是有可能的,但是許多高級的服務(如安全和事務)此時通常不是可交互的。而且,任何專門廠商為同樣的機器的通信所作的優(yōu)化很難起作用,除非所有的應用被建立在同一個ORB產(chǎn)品上。 DCOM 和CORBA/IIOP都依賴于周密管理的環(huán)境。兩個任意的計算機使得DCOM或IIOP 在環(huán)境之外被成功調用(calls out of the box)的幾率是很低的。特別是在考慮安全性的時候尤其是這樣。盡管寫一個能成功地運用DCOM或IIOP的緊縮包(shrink-wrap)應用是可能的,但這樣做要比基于socket的應用要更多地關注細節(jié)。這對于乏味但必需的配置和安裝管理任務特別適用。 DCOM 和 CORBA/IIOP都依賴于相當高技術的運行環(huán)境。盡管進程內的COM似乎特別簡單,但COM/DCOM遠程處理程序絕對不只是幾天就解決的事情。IIOP 是一個比DCOM更容易實現(xiàn)的協(xié)議,但兩個協(xié)議都有相當多的深奧的規(guī)則來處理數(shù)據(jù)排列、類型信息和位操作。這使得一般的程序員在沒有領會ORB產(chǎn)品或OLE32.DLL的情況下去構造一個簡單的CORBA或DCOM調用也變得很困難。 也許對DCOM和CORBA/IIOP來說,最令人難以忍受的一點是它們不能在Internet 上發(fā)揮作用。對DCOM來說,一般用戶的iMac 或廉價的運行Windows 95的PC 兼容機要想使用你的服務器執(zhí)行基于領域認證幾乎是不可能的。更糟的是,如果防火墻或代理服務器分隔開了客戶和服務器的機器,任何IIOP或DCOM包要通過的可能性是很低的,主要是由于大多數(shù)Internet連接技術對HTTP協(xié)議的偏愛所致。盡管一些廠商如Microsoft, Iona和Visigenic都已經(jīng)建立了通道技術,但這些產(chǎn)品很容易對配置錯誤敏感而且它們是不可交互的。 在一個服務器群落中這些問題并不能影響DCOM或IIOP的使用。因為在服務器群落中主機的數(shù)量很少(一般是成百上千,而不是成千上萬),這就抵消了DCOM基于ping的生命周期管理的成本。在服務器群落中,所有主機被一個公共管理域管理的機率很大,使得統(tǒng)一的配置變得可能。相對少量的機器也能保持商業(yè)ORB產(chǎn)品可控制使用的成本,因為只需要更少量的ORB許可權。如果只有IIOP在服務器群落中被使用,就只需要少量的ORB許可權。最后,在服務器群落中所有主機有直接的IP連接也是可能的,這就消除了與防火墻相關的DCOM和 IIOP問題。 HTTP作為一個更好的RPC 在服務器群落中使用DCOM 和CORBA 是通用的做法,但客戶機則使用HTTP進入服務器群落。HTTP與RPC的協(xié)議很相似,它簡單、配置廣泛,并且對防火墻比其它協(xié)議更容易發(fā)揮作用。HTTP請求一般由Web服務器軟件(如IIS和Apache)來處理,但越來越多的應用服務器產(chǎn)品正在支持HTTP作為除DCOM和IIOP外的又一個協(xié)議。 象DCOM和IIOP一樣,HTTP層通過TCP/IP進行請求/響應通信。一個HTTP的客戶端用TCP連接到HTTP服務器。在HTTP中使用的標準端口號是80,但任何其它端口也能被使用。在建立TCP連接后,客戶端可以發(fā)送一個請求消息到服務器端。服務器在處理請求后發(fā)回一個HTTP響應消息到客戶端。請求和響應消息都可以包含任意的傳輸體的信息,通常用Content-Length和Content-Type的 HTTP 頭來標記。下面是一個合法的HTTP請求消息: POST /foobar HTTP/1.1 Host: 209.110.197.12 Content-Type: text/plain Content-Length: 12 Hello, World 你可能已經(jīng)注意到HTTP頭只是一般文本。這使得用包檢查程序或基于文本的Internet工具(如telnet)來診斷HTTP問題變得更容易。HTTP基于文本的屬性也使得HTTP更容易適用于在Web開發(fā)中流行的低技術水平的編程環(huán)境。 HTTP請求的第一行包含三個組件:HTTP方法,請求-URI,協(xié)議版本。在前面的例子中,這些分別對應于POST, /foobar, 和 HTTP/1.1。Internet工程任務組(IETF)已經(jīng)標準化了數(shù)量固定的HTTP方法。GET是HTTP用來訪問Web的方法。 POST是建立應用程序的最常用的HTTP方法。和GET不一樣,POST允許任意數(shù)據(jù)從客戶端發(fā)送到服務器端。請求URI (Uniform Resource Identifier)是一個HTTP服務器端軟件,它用來識別請求的目標的簡單的標識符(它更象一個IIOP/GIOP object_key 或一個DCOM IPID)。關于URIs更多的信息請參照"URIs, URLs, and URNs"。在這個例子中協(xié)議的版本是HTTP/1.1, 它表示遵守RFC 2616的規(guī)則。HTTP/1.1比HTTP/1.0多增加了幾個特性,包括對大塊數(shù)據(jù)傳輸?shù)闹С忠约皩υ趲讉€HTTP請求之間保持TCP連接的支持。 請求的第三行和第四行指定了請求體的尺寸和類型。Content-Length 頭指定了體信息的比特數(shù)。Content-Type類型標識符指定MIME類型為體信息的語法。HTTP (象 DCE一樣) 允許服務器和客戶端協(xié)商用于編制信息的傳輸語法。大多數(shù)DCE應用采用NDR.。大多數(shù)Web應用采用text/html 或其它基于文本的語法。 注意在上面樣例中Content-Length頭與請求體之間的空行。不同的HTTP頭被carriage-return/行碼序列劃定界限。這些頭與體之間用另外的carriage-return/行碼序列來劃定界限。請求接著包括原始字節(jié),這些字節(jié)的語法和長度由Content-Length和Content-Type HTTP 頭來識別。在這個例子中,內容是十二字節(jié)的普通文本字符串"Hello, World"。 在處理了請求之后,HTTP服務器被期望發(fā)回一個HTTP響應到客戶端。響應必須包括一個狀態(tài)代碼來表示請求的結果。響應也可以包含任意的體信息。下面是一個HTTP響應消息: 200 OK Content-Type: text/plain Content-Length: 12 dlroW ,olleH 在這個例子中,服務器返回狀態(tài)代碼200,它是HTTP中標準的成功代碼。如果服務器端不能破解請求代碼,它將返回下列的響應: 400 Bad Request Content-Length: 0 如果HTTP服務器決定到目標URI的請求應該臨時轉向另外的一個不同的URI,下列響將被返回: 307 Temporarily Moved Location: http://209.110.197.44/foobar Content-Length: 0 這個響應告知客戶,請求將能夠通過重新傳遞它到在Location頭中指定的地址來被滿足。 所有的標準狀態(tài)碼和頭都在RFC 2616中被描述。它們中很少的內容與SOAP用戶直接相關,但有一個明顯的例外。在HTTP/1.1,底層的TCP連接在多個請求/響應對之間重用。HTTP Connection頭允許客戶端或服務器中任何一方關閉底層的連接。通過增加下列HTTP頭到請求或響應中,雙方都會要求在處理請求后關閉它們的TCP連接: Connection: close 當與HTTP/1.0軟件交互時,為了保持TCP連接,建議發(fā)送方加入下列HTTP頭到每個請求或響應中: Connection: Keep-Alive 這個頭使缺省的HTTP/1.0協(xié)議在每次響應后重新開始TCP連接的行為無法使用。 HTTP的一個優(yōu)點是它正被廣泛的使用和接受。圖4表示了一個簡單的Java程序,它發(fā)送前面表示的請求并從響應中解析出結果字符串。 下面則是一個簡單的C程序用CGI來讀取來自HTTP請求的字符串并通過HTTP響應把它的逆序串返回。 #include <stdio.h> int main(int argc, char **argv) { char buf[4096]; int cb = read(0, buf, sizeof(buf)); buf[cb] = 0; strrev(buf); printf("200 OK\r\n");p> printf("Content-Type: text/plain\r\n"); printf("Content-Length: %d\r\n", cb); printf("\r\n"); printf(buf); return 0; 服務器的實現(xiàn)是用Java servlet,以避免CGI的每個請求一個進程的開銷。 一般 來說CGI是花費代價最小的寫HTTP服務器端代碼的方法。實際上,每一個HTTP服務器端產(chǎn)品都提供了一個更有效的機制來讓你的代碼處理一個HTTP請求。IIS提供了ASP和ISAPI作為寫HTTP代碼的機制。Apache允許你用運行在Apache后臺程序中的 C或Perl來寫模塊。大多數(shù)應用服務器軟件允許你寫Java servlet,COM組件,EJB Session beans或基于可攜帶對象適配器(POA)接口的CORBA servants。 |
|
|