REST 樣式與 SOAP 樣式 Web 服務(wù)之間關(guān)系的概覽 ![]() |
級別: 初級 James M. Snell, 軟件工程師, IBM 2004 年 11 月 01 日 Bloglines API 最近的發(fā)布引發(fā)了又一輪關(guān)于是使用 REpresentational State Transfer(REST)還是使用簡單對象訪問協(xié)議(Simple Object Access Protocol,SOAP)Web 服務(wù)的討論。然而與一些人所認為的相反,這些不同的面向服務(wù)體系結(jié)構(gòu)(Service-Oriented Architecture,SOA)設(shè)計模式不是互斥的。也不是說一個就比另外一個優(yōu)越。對于不同的應(yīng)用場景,它們每一個都有自己相對的優(yōu)勢和劣勢,并且它們都是解決實際客戶的實際問題的有效方法。訣竅就在于能夠決定采用哪一種方法。答案可能比您想象的更簡單。 每當一些 Web 應(yīng)用服務(wù)提供方提出允許開發(fā)者集成他們的服務(wù)的 Web 服務(wù) API 時,大家都非常關(guān)心由 API 實現(xiàn)的互操作設(shè)計模式。如果 API 使用的是 REST 樣式的互操作,REST 方法的擁護者就會將該 API 作為說明為什么 REST 樣式服務(wù)比 SOAP 樣式服務(wù)更優(yōu)越的重要例子而加以稱贊;同樣地,如果 API 使用 SOAP 樣式 Web 服務(wù)模式,情況也類似。似乎很少有人關(guān)心這樣的一個事實,模式的選擇主要取決于正在被執(zhí)行的應(yīng)用程序的類型,并且像所有優(yōu)秀的體系結(jié)構(gòu)決策一樣,開發(fā)者應(yīng)該將他們的選擇基于正在被開發(fā)的應(yīng)用程序的特定技術(shù)需求和特性,而不是基于針對單一體系結(jié)構(gòu)方法的一些特殊偏好。 從基本原理層次上說,REST 樣式和 SOAP 樣式 Web 服務(wù)的區(qū)別取決于應(yīng)用程序是面向 資源的還是面向 活動的。 面向資源服務(wù)集中于明確的數(shù)據(jù)對象,一些基本、標準的操作可以依據(jù)這些數(shù)據(jù)對象而執(zhí)行。如權(quán)威的 Gang of Four(GoF) 設(shè)計模式這本書所述,對于熟悉面向?qū)ο笤O(shè)計模式概念的開發(fā)者來說,面向資源服務(wù)與基本 Memento 模式類似。實際上,服務(wù)提供方維護一組資源,并且公開一組基本操作來執(zhí)行以下任務(wù):
根據(jù)定義,REST 樣式 Web 服務(wù)是面向資源的服務(wù)。您可以通過統(tǒng)一資源標識符(Universal Resource Identifier,URI)來識別和定位資源,并且針對這些資源而執(zhí)行的操作是通過 HTTP 規(guī)范定義的。其核心操作包括:
在許多方面,REST 樣式 Web 服務(wù)與 SQL、元組空間(tuple spaces)、簡單消息列隊等技術(shù)相似。它們都使用普通的簡單操作針對明確的資源起作用。
在每一個案例中,服務(wù)接口的設(shè)計允許您移動關(guān)于資源的信息,讓其依賴于請求方來指出希望通過這些信息來做什么。 與此相對的是 面向活動的資源。該類型的應(yīng)用程序集中于您可能執(zhí)行的操作,而不是集中于操作所依靠的資源?;顒臃?wù)的一個簡單的例子就是銀行事務(wù),在那里用戶可以把錢從一個賬戶轉(zhuǎn)移到另一個賬戶上。用戶不想直接操作資源(錢、銀行賬戶等等),他們只想告訴銀行他們想要達到的目的,并且讓銀行根據(jù)他們的利益對資源進行處理。用 GoF 術(shù)語來描述應(yīng)用程序:
面向資源服務(wù)不管資源的類型怎樣,執(zhí)行的操作可以保持相對不變,與面向資源服務(wù)不同,面向活動服務(wù)的操作完全依賴于正在執(zhí)行的活動類型。例如,銀行服務(wù)可以公開一個名為 在面向資源的服務(wù)中,一組普通操作擔當支持性的工作角色,為客戶端提供訪問和操作資源。然而,資源是關(guān)注的中心,如下面 圖 1 所示。 圖 1. 面向資源服務(wù)與面向活動服務(wù)的比較 ![]() 在面向活動服務(wù)中,對客戶端請求執(zhí)行的每個活動的單一操作來說,操作是關(guān)注的中心。 SOAP 樣式 Web 服務(wù)通常是面向活動的。 WSDL 文檔定義并描述特定于服務(wù)的操作。操作由特定于服務(wù)的消息交換組成。每一個操作都是一個可以執(zhí)行的活動。那些正在被執(zhí)行的操作所針對的內(nèi)容通常是不相關(guān)的。正如 Web 服務(wù)資源框架系列規(guī)范所描述的,資源可以隱含在活動之中,但是這種隱含與活動的定義不相關(guān),并且只是為了改進執(zhí)行活動所依賴的上下文。與針對資源而執(zhí)行活動的面向資源服務(wù)相比,它和用來訪問資源的服務(wù)接口互不相關(guān)。
Bloglines 是一個基于 Web 的應(yīng)用服務(wù),它允許個人對 weblog 和新聞的各種訂閱保持跟蹤,這些訂閱內(nèi)容以 Really Simple Syndication(RSS)和 Atom 提供的形式交付。 Bloglines 服務(wù)根本上是面向資源的。用戶創(chuàng)建、更新、和刪除訂閱,并且定期訪問服務(wù)來了解自上次訪問站點后發(fā)生了哪些更新。Bloglines API 利用 REST 樣式 Web 服務(wù)接口適當?shù)胤从沉嗣嫦蛸Y源的特性。 特別地,對于 Bloglines 來說重要的是訂閱的用戶集合,如眾所周知的 blogroll。單個 blogroll 會由許多不同的訂閱組成。一個 訂閱指向一個 RSS 或者一個 Atom 提供。 Blogrolls 和訂閱都是資源。Bloglines API 使用基本 HTTP 操作來檢索關(guān)于用戶的 blogroll 和訂閱資源的當前狀態(tài)信息。 例如,要訪問用戶 blogroll 的當前快照,用戶向 URI 為訪問特定訂閱的當前快照,用戶對 URI 要返回當前用戶 blogroll 中未讀的訂閱條目的數(shù)量,用戶可以向 URI Bloglines API 參與的唯一一件事是允許有計劃的訪問 blogrolls 和訂閱資源。API 不關(guān)心客戶端訪問 blogrolls 或訂閱時會如何處理它們。 提供一個對照,與 IBM 最近實現(xiàn)的概念驗證工程做比較來闡明 Web 服務(wù)在自動化醫(yī)院患者紀錄的訪問、處方的編寫、手術(shù)的安排等方面的用途。不做詳細的說明(與客戶端的非公開協(xié)議涉及的內(nèi)容),為系統(tǒng)建立的服務(wù)接口的集合完全集中于用戶在系統(tǒng)中執(zhí)行的活動。例如,為患者安排手續(xù)或檢查,并請求檢查結(jié)果的有效性等事件的異步通知?;颊叩臋n案(資源)是系統(tǒng)的一個很重要的方面,它通常在全部的應(yīng)用程序中起到支持的作用,但不是系統(tǒng)的主要焦點。更確切地說,醫(yī)院原型是一個面向活動的服務(wù),這由它的 SOAP 樣式 Web 服務(wù)體系結(jié)構(gòu)確切的反映出來。 要點很簡單:REST 和 SOAP 的選擇歸結(jié)為對您的特定應(yīng)用程序的最重要部分的理解。如果您的應(yīng)用程序主要集中在訪問信息資源的能力(如 Bloglines 服務(wù)),那么您用的主要是面向資源服務(wù),并且您的應(yīng)用程序應(yīng)該是 REST 樣式的設(shè)計模式。這里應(yīng)該優(yōu)先考慮 Amazon、del.icio.us、Flickr 還有其他的一些廠商(請參閱 參考資料)提供的服務(wù) API。然而,如果您的應(yīng)用程序主要集中于被執(zhí)行的活動(這些活動與所依賴的資源不相關(guān)),那么您的服務(wù)是面向活動的,并且應(yīng)該利用 SOAP 樣式的設(shè)計模式。
基于 REST 的模式的支持者常常指出它的體系結(jié)構(gòu)化的簡單性,并將其和 SOAP 型的 Web 服務(wù)規(guī)范的復雜性相比較,以此來說明為什么 REST 是更優(yōu)越的方法。正如我已經(jīng)闡明的,這一論斷是有缺陷的,這兩種方法要解決不同類型的問題。基于 Web 的應(yīng)用程序服務(wù),例如 Bloglines、Amazon、flikr、del.icio.us 等等,要面對不同類型的問題,這不是說說那么簡單。醫(yī)院需要將定制規(guī)程、編寫處方的內(nèi)部流程自動化,因此要求一個不同的體系結(jié)構(gòu)化方法。這就是設(shè)計模式存在的原因 -- 不同的方法解決不同的問題。 在特定業(yè)務(wù)需求上下文之外進行比較,REST 體系結(jié)構(gòu)表面上好像遠不及該行業(yè)提出的各種 WS-* 規(guī)范所定義的 SOAP Web 服務(wù)體系結(jié)構(gòu)復雜。而且,在某些關(guān)鍵地方它的功能也遠沒有那么強大??煽肯⑹且粋€主要的例子。HTTP 不是一個可靠協(xié)議。這里沒有使用一次且僅一次(once-and-only-once)或者重試直至成功(retry-until-success)的語義以允許可靠傳輸 HTTP 請求的機制。REST/HTTP 中也沒有在基本 HTTP 代理機制之外進行消息路由的機制。在 REST 服務(wù)中的安全性上下文也通常局限于 HTTP 協(xié)議提供的安全機制,除非應(yīng)用程序選擇采用一些外部定義的安全機制(例如,一個 REST 服務(wù)實際上能返回數(shù)字簽名或者加密 SOAP 消息來響應(yīng) HTTP GET 請求)。 對于如 Bloglines 之類的服務(wù),這些功能限制不是關(guān)鍵,因為由 HTTP 提供的基本選項足以滿足應(yīng)用程序的需要。API 不需要:
這并不意味著其他應(yīng)用程序不要求由基于活動的方法所提供的增強功能。 不要理解錯我的意思,所有這些在 REST 樣式服務(wù)中做的事情至少從理論上講是完全可行的。關(guān)鍵的問題是沒有人定義過這樣做的一致的標準方法。既然如此,舉例來說,任何人使用任何方法在 REST 樣式接口中做這樣的工作(如異步事件通知或可靠消息傳輸),都將會是特定于實現(xiàn)的一次性服務(wù),通常不會被其它 REST 樣式的服務(wù)支持。然而需要指出的更重要的問題是,通常與適合于面向資源的服務(wù)相比,這些擴展的功能更適合于面向活動的服務(wù),因此在面向活動的 SOAP 樣式服務(wù)領(lǐng)域里,我們見到更多的規(guī)范和更大的復雜性也就不奇怪了。 注意:如果處理適當,復雜性并不是一件壞事。是的,有很多 WS-* 規(guī)范,涉及了很大范圍的技術(shù)主題。從總體上看,它們代表了更高的復雜性。然而,它們定義的方法包含這樣的概念,即僅僅提取對應(yīng)用程序必要的一部分規(guī)范。沒有人會期待每一個 Web 服務(wù)都能執(zhí)行全部的 WS-* 規(guī)范。
最后,行業(yè)繼續(xù)朝著面向服務(wù)體系結(jié)構(gòu)方向前進,這是非常重要的。做出 REST 樣式和 SOAP 樣式的選擇,應(yīng)該與為給定應(yīng)用程序組件實現(xiàn) 命令、中介方、觀測器、策略或是訪問者設(shè)計模式之間進行選擇一樣謹慎。簡單地說,那只不過是一個基于業(yè)務(wù)和應(yīng)用需要的設(shè)計策略,但卻會嚴重影響您的應(yīng)用程序的使用和將來的發(fā)展。然而,比 Web 服務(wù)設(shè)計模式的選擇更為重要的是提供 Web 服務(wù)的選擇。無論您選擇實現(xiàn)哪種樣式的服務(wù),這都是非常關(guān)鍵的。
|