soap(simple object access protocal) 技術(shù)有助于實(shí)現(xiàn)大量異構(gòu)程序和平臺(tái)之間的互操作性,從而使存在的應(yīng)用能夠被廣泛的用戶所訪問(wèn)。soap是把成熟的基于http的web技術(shù)與xml的靈活性和可擴(kuò)展性組合在了一起。
這篇文章帶你全面回顧對(duì)象遠(yuǎn)程進(jìn)程調(diào)用(orpc)技術(shù)的歷程,以幫助你理解soap技術(shù)的基礎(chǔ),以及它克服存在技術(shù)(如corba和dcom)的許多缺陷的方法。隨后講述詳細(xì)的soap編碼規(guī)則,并把焦點(diǎn)放在soap是怎樣映射到存在的orpc概念上的。
引言:
當(dāng)我在1984年開(kāi)始把計(jì)算作為我的職業(yè)的時(shí)候,大多數(shù)程序員并不關(guān)心網(wǎng)絡(luò)協(xié)議。但是在九十年代網(wǎng)絡(luò)變得無(wú)所不在,現(xiàn)在如果有誰(shuí)使用計(jì)算機(jī)卻不使用某種形式網(wǎng)絡(luò)連接是很難以想象的。今天,一般的程序員對(duì)建立可擴(kuò)展的分布式應(yīng)用表現(xiàn)出更大的興趣,而不再只是關(guān)注于用mfc實(shí)現(xiàn)個(gè)性化的可浮動(dòng)半透明非矩形的coolbars了。
程序員通常喜歡用編程模型來(lái)思考問(wèn)題,而很少考慮網(wǎng)絡(luò)協(xié)議。盡管這樣做通常是很好的,但在這篇文章中我將討論的soap是一個(gè)沒(méi)有明顯的編程模型的網(wǎng)絡(luò)協(xié)議。這并不意味著soap的體系結(jié)構(gòu)從根本上會(huì)改變你編程的方式。相反,soap的一個(gè)主要目標(biāo)是使存在的應(yīng)用能被更廣泛的用戶所使用。為了實(shí)現(xiàn)這個(gè)目的,沒(méi)有任何soap api或soap 對(duì)象請(qǐng)求代理(soap orb),soap是假設(shè)你將使用盡可能多的存在的技術(shù)。幾個(gè)主要的corba廠商已經(jīng)承諾在他們的orb產(chǎn)品中支持soap協(xié)議。微軟也承諾在將來(lái)的com版本中支持soap。
developmentor已經(jīng)開(kāi)發(fā)了參考實(shí)現(xiàn),它使得在任何平臺(tái)上的任何java或perl程序員都可以使用soap。
在soap后面的指導(dǎo)理念是“它是第一個(gè)沒(méi)有發(fā)明任何新技術(shù)的技術(shù)”。soap采用了已經(jīng)廣泛使用的兩個(gè)協(xié)議:http和xml。http用于實(shí)現(xiàn)soap的rpc風(fēng)格的傳輸,而xml是它的編碼模式。采用幾行代碼和一個(gè)xml解析器,http服務(wù)器(如ms的iis或apache)立刻成為了soap的orbs。 因?yàn)槟壳俺^(guò)一半的web服務(wù)器采用iis或apache, soap將會(huì)從這兩個(gè)產(chǎn)品的廣泛而可靠的使用中獲取利益。這并不意味著所有的soap請(qǐng)求必須通過(guò)web服務(wù)器來(lái)路由,傳統(tǒng)的web 服務(wù)器只是分派soap請(qǐng)求的一種方式。因此web服務(wù)如iis或apache對(duì)建立soap使能的應(yīng)用是充分的,但決不是必要的。
正如這篇文章將要描述的,soap簡(jiǎn)單地用xml來(lái)編碼http的傳輸內(nèi)容。soap最常用的應(yīng)用是作為一個(gè)rpc協(xié)議。為了理解soap怎樣工作,有必要簡(jiǎn)要回顧一下rpc協(xié)議的歷史。
rpcs的歷史
建立分布式應(yīng)用的兩個(gè)主要通信模型是消息傳送(經(jīng)常與隊(duì)列組合在一起)和請(qǐng)求/響應(yīng)。消息傳遞系統(tǒng)允許通信任何一方在任何時(shí)間發(fā)送消息。請(qǐng)求/響應(yīng)協(xié)議把通信模式限制在請(qǐng)求/響應(yīng)的雙方。基于消息的應(yīng)用強(qiáng)烈地意識(shí)到它們正在與外部的并行進(jìn)程進(jìn)行通信,并且需要一個(gè)顯式的設(shè)計(jì)風(fēng)格。基于請(qǐng)求/響應(yīng)的應(yīng)用更象一個(gè)單進(jìn)程的應(yīng)用,因?yàn)榘l(fā)送請(qǐng)求的應(yīng)用或多或少被阻塞直至收到來(lái)自另一個(gè)進(jìn)程的響應(yīng)。這使得請(qǐng)求/響應(yīng)通信自然地適合于rpc應(yīng)用。
盡管消息通信和請(qǐng)求/響應(yīng)各有他們的優(yōu)點(diǎn),他們都是可以用對(duì)方來(lái)實(shí)現(xiàn)的。消息系統(tǒng)可以用較底層的請(qǐng)求/響應(yīng)協(xié)議來(lái)建立。如微軟的message queue server (msmq)內(nèi)部采用了dce rpc來(lái)建立大多數(shù)的控制邏輯。rpc系統(tǒng)也可以采用較底層的消息系統(tǒng)來(lái)建立。msmq提供的關(guān)聯(lián) id正是為了這個(gè)目的。不管評(píng)價(jià)如何,大多數(shù)的應(yīng)用仍趨向于使用rpc協(xié)議,因?yàn)樗鼈儚V泛的使用,它們更簡(jiǎn)單的設(shè)計(jì),以及更自然的到傳統(tǒng)的編程技術(shù)的映射。
在八十年代,兩個(gè)主要的rpc協(xié)議是sun rpc 和dce rpc。最流行的sun rpc應(yīng)用是大多數(shù)unix系統(tǒng)所使用的network file system (nfs)。最流行的dce rpc應(yīng)用則是windows nt?,它采用dce rpc 協(xié)議來(lái)實(shí)現(xiàn)許多系統(tǒng)服務(wù)。這兩個(gè)協(xié)議被證明適用于很大范圍的應(yīng)用。但是,在八十年代末期,面向?qū)ο蠹夹g(shù)的風(fēng)靡使軟件界沉迷于在面向?qū)ο笳Z(yǔ)言和基于rpc的通信之間建立一個(gè)紐帶。
在九十年代產(chǎn)生的對(duì)象rpc (orpc) 協(xié)議正是試圖把面向?qū)ο蠛途W(wǎng)絡(luò)協(xié)議聯(lián)系起來(lái)。orpc 和 rpc 協(xié)議的主要不同是orpc代碼化了從通信終端到語(yǔ)言級(jí)對(duì)象的映射。在每個(gè)orpc請(qǐng)求的頭中都有一個(gè)cookie,服務(wù)器端的程序能用它來(lái)定位在服務(wù)器進(jìn)程中的目標(biāo)對(duì)象。通常這個(gè)cookie只是一個(gè)對(duì)數(shù)組的索引,但其它技術(shù)也經(jīng)常被使用,如用符號(hào)名作為hash表的鍵。
目前兩個(gè)主要的oprc協(xié)議是dcom 和 corba的 internet inter-orb protocol (iiop) 或更一般的general inter-orb protocol (giop)。dcom和iiop/giop的請(qǐng)求格式非常相似。兩個(gè)協(xié)議都用一個(gè)對(duì)象端點(diǎn)id來(lái)確定目標(biāo)對(duì)象,用方法標(biāo)識(shí)符來(lái)決定調(diào)用哪個(gè)方法。
這兩個(gè)協(xié)議主要有兩點(diǎn)不同:主要的一點(diǎn)不同是采用iiop/giop時(shí),接口標(biāo)識(shí)符是隱含的,因?yàn)橐粋€(gè)給定的corba對(duì)象只實(shí)現(xiàn)一個(gè)接口(盡管omg當(dāng)前正在進(jìn)行每個(gè)對(duì)象有多個(gè)接口支持的標(biāo)準(zhǔn)化工作)。dcom與iiop/giop請(qǐng)求的另一個(gè)細(xì)微差別是在傳輸體中參數(shù)值的格式。在dcom中,傳輸體用網(wǎng)絡(luò)數(shù)據(jù)表達(dá)(ndr)的格式來(lái)寫,在iiop/giop中,傳輸體用公共數(shù)據(jù)表達(dá)(cdr)的格式來(lái)寫。ndr和 cdr分別處理在各種平臺(tái)上的不同的數(shù)據(jù)表達(dá)。但是在這兩種格式之間有一些小的差別,這使它們相互之間并不兼容。
在orpc與rpc協(xié)議之間的另一個(gè)重要的不同是通信端點(diǎn)的命名方式。在orpc協(xié)議中,對(duì)于orpc端點(diǎn)的一些可傳遞的表達(dá)方式被要求在網(wǎng)絡(luò)之間傳遞對(duì)象引用。在corba/iiop,這個(gè)表達(dá)方式被稱為可交互的對(duì)象引用(ior)。iors包含用緊湊格式表達(dá)的尋址信息,使用了它任何corba產(chǎn)品都可以決定一個(gè)對(duì)象端點(diǎn)。在dcom中,這種表達(dá)方式被稱為objref,它組合了分布的引用計(jì)算和端點(diǎn)/對(duì)象標(biāo)識(shí)。corba和dcom都提供了在網(wǎng)絡(luò)上尋找對(duì)象端點(diǎn)的高級(jí)機(jī)制,但最終這些機(jī)制都映射回到了iors或objrefs。
目前的技術(shù)存在的問(wèn)題?
盡管dcom和iiop都是固定的協(xié)議,業(yè)界還沒(méi)有完全轉(zhuǎn)向其中任何一個(gè)協(xié)議。沒(méi)有融合的部分原因是文化的問(wèn)題所致。而且在當(dāng)一些組織試圖標(biāo)準(zhǔn)化一個(gè)或另一個(gè)協(xié)議的時(shí)候,兩個(gè)協(xié)議的技術(shù)適用性就被提出質(zhì)疑。傳統(tǒng)上認(rèn)為dcom和corba都是合理服務(wù)器到服務(wù)器端的通信協(xié)議。但是,二者對(duì)客戶到服務(wù)器端的通信都存在明顯的弱點(diǎn),尤其是客戶機(jī)被散布在internet上的時(shí)候。
dcom 和 corba/iiop都是依賴于單個(gè)廠商的解決方案來(lái)最大優(yōu)勢(shì)地使用協(xié)議。盡管兩個(gè)協(xié)議都在各種平臺(tái)和產(chǎn)品上被實(shí)現(xiàn)了,但現(xiàn)實(shí)是選定的發(fā)布需要采用單一廠商的實(shí)現(xiàn)。在dcom的情況下,這意味著每個(gè)機(jī)器要運(yùn)行在windows nt。(盡管dcom已經(jīng)被轉(zhuǎn)移到其它平臺(tái),但它只在windows?上獲得了廣泛的延伸)。在corba情況下,這意味著每個(gè)機(jī)器要運(yùn)行同樣的orb產(chǎn)品。的確讓兩個(gè)corba產(chǎn)品用iiop相互調(diào)用是有可能的,但是許多高級(jí)的服務(wù)(如安全和事務(wù))此時(shí)通常不是可交互的。而且,任何專門廠商為同樣的機(jī)器的通信所作的優(yōu)化很難起作用,除非所有的應(yīng)用被建立在同一個(gè)orb產(chǎn)品上。
dcom 和corba/iiop都依賴于周密管理的環(huán)境。兩個(gè)任意的計(jì)算機(jī)使得dcom或iiop 在環(huán)境之外被成功調(diào)用(calls out of the box)的幾率是很低的。特別是在考慮安全性的時(shí)候尤其是這樣。盡管寫一個(gè)能成功地運(yùn)用dcom或iiop的緊縮包(shrink-wrap)應(yīng)用是可能的,但這樣做要比基于socket的應(yīng)用要更多地關(guān)注細(xì)節(jié)。這對(duì)于乏味但必需的配置和安裝管理任務(wù)特別適用。
dcom 和 corba/iiop都依賴于相當(dāng)高技術(shù)的運(yùn)行環(huán)境。盡管進(jìn)程內(nèi)的com似乎特別簡(jiǎn)單,但com/dcom遠(yuǎn)程處理程序絕對(duì)不只是幾天就解決的事情。iiop 是一個(gè)比dcom更容易實(shí)現(xiàn)的協(xié)議,但兩個(gè)協(xié)議都有相當(dāng)多的深?yuàn)W的規(guī)則來(lái)處理數(shù)據(jù)排列、類型信息和位操作。這使得一般的程序員在沒(méi)有領(lǐng)會(huì)orb產(chǎn)品或ole32.dll的情況下去構(gòu)造一個(gè)簡(jiǎn)單的corba或dcom調(diào)用也變得很困難。
也許對(duì)dcom和corba/iiop來(lái)說(shuō),最令人難以忍受的一點(diǎn)是它們不能在internet 上發(fā)揮作用。對(duì)dcom來(lái)說(shuō),一般用戶的imac 或廉價(jià)的運(yùn)行windows 95的pc 兼容機(jī)要想使用你的服務(wù)器執(zhí)行基于領(lǐng)域認(rèn)證幾乎是不可能的。更糟的是,如果防火墻或代理服務(wù)器分隔開(kāi)了客戶和服務(wù)器的機(jī)器,任何iiop或dcom包要通過(guò)的可能性是很低的,主要是由于大多數(shù)internet連接技術(shù)對(duì)http協(xié)議的偏愛(ài)所致。盡管一些廠商如microsoft, iona和visigenic都已經(jīng)建立了通道技術(shù),但這些產(chǎn)品很容易對(duì)配置錯(cuò)誤敏感而且它們是不可交互的。
在一個(gè)服務(wù)器群落中這些問(wèn)題并不能影響dcom或iiop的使用。因?yàn)樵诜?wù)器群落中主機(jī)的數(shù)量很少(一般是成百上千,而不是成千上萬(wàn)),這就抵消了dcom基于ping的生命周期管理的成本。在服務(wù)器群落中,所有主機(jī)被一個(gè)公共管理域管理的機(jī)率很大,使得統(tǒng)一的配置變得可能。相對(duì)少量的機(jī)器也能保持商業(yè)orb產(chǎn)品可控制使用的成本,因?yàn)橹恍枰倭康膐rb許可權(quán)。如果只有iiop在服務(wù)器群落中被使用,就只需要少量的orb許可權(quán)。最后,在服務(wù)器群落中所有主機(jī)有直接的ip連接也是可能的,這就消除了與防火墻相關(guān)的dcom和 iiop問(wèn)題。
http作為一個(gè)更好的rpc
在服務(wù)器群落中使用dcom 和corba 是通用的做法,但客戶機(jī)則使用http進(jìn)入服務(wù)器群落。http與rpc的協(xié)議很相似,它簡(jiǎn)單、配置廣泛,并且對(duì)防火墻比其它協(xié)議更容易發(fā)揮作用。http請(qǐng)求一般由web服務(wù)器軟件(如iis和apache)來(lái)處理,但越來(lái)越多的應(yīng)用服務(wù)器產(chǎn)品正在支持http作為除dcom和iiop外的又一個(gè)協(xié)議。
象dcom和iiop一樣,http層通過(guò)tcp/ip進(jìn)行請(qǐng)求/響應(yīng)通信。一個(gè)http的客戶端用tcp連接到http服務(wù)器。在http中使用的標(biāo)準(zhǔn)端口號(hào)是80,但任何其它端口也能被使用。在建立tcp連接后,客戶端可以發(fā)送一個(gè)請(qǐng)求消息到服務(wù)器端。服務(wù)器在處理請(qǐng)求后發(fā)回一個(gè)http響應(yīng)消息到客戶端。請(qǐng)求和響應(yīng)消息都可以包含任意的傳輸體的信息,通常用content-length和content-type的 http 頭來(lái)標(biāo)記。下面是一個(gè)合法的http請(qǐng)求消息:
post /foobar http/1.1
host: 209.110.197.12
content-type: text/plain
content-length: 12
hello, world
你可能已經(jīng)注意到http頭只是一般文本。這使得用包檢查程序或基于文本的internet工具(如telnet)來(lái)診斷http問(wèn)題變得更容易。http基于文本的屬性也使得http更容易適用于在中流行的低技術(shù)水平的編程環(huán)境。
http請(qǐng)求的第一行包含三個(gè)組件:http方法,請(qǐng)求-uri,協(xié)議版本。在前面的例子中,這些分別對(duì)應(yīng)于post, /foobar, 和 http/1.1。internet工程任務(wù)組(ietf)已經(jīng)標(biāo)準(zhǔn)化了數(shù)量固定的http方法。get是http用來(lái)訪問(wèn)web的方法。 post是建立應(yīng)用程序的最常用的http方法。和get不一樣,post允許任意數(shù)據(jù)從客戶端發(fā)送到服務(wù)器端。請(qǐng)求uri (uniform resource identifier)是一個(gè)http服務(wù)器端軟件,它用來(lái)識(shí)別請(qǐng)求的目標(biāo)的簡(jiǎn)單的標(biāo)識(shí)符(它更象一個(gè)iiop/giop object_key 或一個(gè)dcom ipid)。關(guān)于uris更多的信息請(qǐng)參照"uris, urls, and urns"。在這個(gè)例子中協(xié)議的版本是http/1.1, 它表示遵守rfc 2616的規(guī)則。http/1.1比http/1.0多增加了幾個(gè)特性,包括對(duì)大塊數(shù)據(jù)傳輸?shù)闹С忠约皩?duì)在幾個(gè)http請(qǐng)求之間保持tcp連接的支持。
請(qǐng)求的第三行和第四行指定了請(qǐng)求體的尺寸和類型。content-length 頭指定了體信息的比特?cái)?shù)。content-type類型標(biāo)識(shí)符指定mime類型為體信息的語(yǔ)法。http (象 dce一樣) 允許服務(wù)器和客戶端協(xié)商用于編制信息的傳輸語(yǔ)法。大多數(shù)dce應(yīng)用采用ndr.。大多數(shù)web應(yīng)用采用text/html 或其它基于文本的語(yǔ)法。
注意在上面樣例中content-length頭與請(qǐng)求體之間的空行。不同的http頭被carriage-return/行碼序列劃定界限。這些頭與體之間用另外的carriage-return/行碼序列來(lái)劃定界限。請(qǐng)求接著包括原始字節(jié),這些字節(jié)的語(yǔ)法和長(zhǎng)度由content-length和content-type http 頭來(lái)識(shí)別。在這個(gè)例子中,內(nèi)容是十二字節(jié)的普通文本字符串"hello, world"。
在處理了請(qǐng)求之后,http服務(wù)器被期望發(fā)回一個(gè)http響應(yīng)到客戶端。響應(yīng)必須包括一個(gè)狀態(tài)代碼來(lái)表示請(qǐng)求的結(jié)果。響應(yīng)也可以包含任意的體信息。下面是一個(gè)http響應(yīng)消息:
200 ok
content-type: text/plain
content-length: 12
dlrow ,olleh
在這個(gè)例子中,服務(wù)器返回狀態(tài)代碼200,它是http中標(biāo)準(zhǔn)的成功代碼。如果服務(wù)器端不能破解請(qǐng)求代碼,它將返回下列的響應(yīng):
400 bad request
content-length: 0
如果http服務(wù)器決定到目標(biāo)uri的請(qǐng)求應(yīng)該臨時(shí)轉(zhuǎn)向另外的一個(gè)不同的uri,下列響將被返回:
307 temporarily moved
location: http://209.110.197.44/foobar
content-length: 0
這個(gè)響應(yīng)告知客戶,請(qǐng)求將能夠通過(guò)重新傳遞它到在location頭中指定的地址來(lái)被滿足。
所有的標(biāo)準(zhǔn)狀態(tài)碼和頭都在rfc 2616中被描述。它們中很少的內(nèi)容與soap用戶直接相關(guān),但有一個(gè)明顯的例外。在http/1.1,底層的tcp連接在多個(gè)請(qǐng)求/響應(yīng)對(duì)之間重用。http connection頭允許客戶端或服務(wù)器中任何一方關(guān)閉底層的連接。通過(guò)增加下列http頭到請(qǐng)求或響應(yīng)中,雙方都會(huì)要求在處理請(qǐng)求后關(guān)閉它們的tcp連接:
connection: close
當(dāng)與http/1.0軟件交互時(shí),為了保持tcp連接,建議發(fā)送方加入下列http頭到每個(gè)請(qǐng)求或響應(yīng)中:
connection: keep-alive
這個(gè)頭使缺省的http/1.0協(xié)議在每次響應(yīng)后重新開(kāi)始tcp連接的行為無(wú)法使用。
http的一個(gè)優(yōu)點(diǎn)是它正被廣泛的使用和接受。圖4表示了一個(gè)簡(jiǎn)單的java程序,它發(fā)送前面表示的請(qǐng)求并從響應(yīng)中解析出結(jié)果字符串。
下面則是一個(gè)簡(jiǎn)單的c程序用cgi來(lái)讀取來(lái)自http請(qǐng)求的字符串并通過(guò)http響應(yīng)把它的逆序串返回。
#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;
服務(wù)器的實(shí)現(xiàn)是用java servlet,以避免cgi的每個(gè)請(qǐng)求一個(gè)進(jìn)程的開(kāi)銷。
一般 來(lái)說(shuō)cgi是花費(fèi)代價(jià)最小的寫http服務(wù)器端代碼的方法。實(shí)際上,每一個(gè)http服務(wù)器端產(chǎn)品都提供了一個(gè)更有效的機(jī)制來(lái)讓你的代碼處理一個(gè)http請(qǐng)求。iis提供了asp和isapi作為寫http代碼的機(jī)制。apache允許你用運(yùn)行在apache后臺(tái)程序中的 c或perl來(lái)寫模塊。大多數(shù)應(yīng)用服務(wù)器軟件允許你寫java servlet,com組件,ejb session beans或基于可攜帶對(duì)象適配器(poa)接口的corba servants。
新聞熱點(diǎn)
疑難解答
圖片精選