• REST會是SOA的未來嗎?

    0
    Java SOA C/C++ REST Go 17463 次瀏覽

      好像無論我們到哪兒都能聽到這樣的說法:REST 將會是 SOA 的未來。很多刊物也將 REST 和 SOAP 與 WS*[1]標準進行比較,但這些比較看起來都太過簡單了。近來出現了兩種較為主流的方法——本真 REST(true REST)以及將 REST 作為面向服務的技術方法(又稱 REST Web 服務[2])。本文討論的重點為:是否其中一種方法能夠改進 SOA 實現。

      面向 SOA 的本真 REST

      本真 REST 當然是對面向資源架構的一種實現,而并非一種純粹的技術決策。所以當討論本真 REST 時,真正應該討論的問題是:其基礎支撐——面向資源的架構(ROA)——是否真的適合作為你的 SOA 實現。

      為正確評估該問題,讓我們首先回想一下 SOA 的架構風格,它是基于企業業務架構的功能性分解,并且引入了兩個高層次的抽象:企業業務服務和業務流程。企業業務服務代表的是現有 IT 能力(和企業的業務功能相一致)。業務流程編排業務服務,并定義業務的整體功能。

      而 REST 是一組被稱之為面向資源架構(ROA)的架構準則。ROA 構建在資源這一概念之上;每個資源都是一個能夠直接訪問的分布式組件,可通過一個標準的、通用的接口來處理。所以,面向資源的架構(ROA)其最根本的還是一種基于資源的分解[3]

      為了評估本真 REST 是否適用于面向 SOA 的實現,我們真正需要回答的問題是,“服務和資源之間到底是什么關系?”

      服務 vs. 資源

      何為服務?

      在最簡單的情況下,服務可以被定義為一個自包含、獨立開發、可部署、可管理和可維護的軟件實現,它從整體上為企業提供特定的與業務相關的功能,并且在設計上是“可集成的”。“服務”可以通過動詞(verb)來定義(例如,“驗證客戶信用積分”,這描述了服務實現的業務功能)。

      服務并不是某個編程結構或一組 APIs,而是一個用于實現企業解決方案的架構(設計單元、實現以及維護)和部署構件。服務接口(尤其對某個給定的服務而言)定義服務功能,并且可由多種 方式實現。存在兩種基本的定義服務接口的方法——RPC 風格和消息(messaging)風格,RPC 風格實現使用服務調用語義并且通過服務接口中的一組參數來定義。而消息風格的服務接口被有效地固定(本質上只需要進行“執行”操作)使用 XML 文檔作為輸入和輸出(這和 GoF 設計模式非常相似)。在這種情況下,服務語義是由輸入和輸出消息的語義來確定[4]

      過去,服務通常被定義為一組方法的集合,但正如參考文獻[2]中解釋的那樣,這些方法彼此相互獨立[5],但作為整體它們共享同一個命名空間,這樣簡化了對服務的管理。

      何為資源?

      在最簡單的情況下,資源可以被定義為一個可直接訪問的、獨立開發的、可部署的、可管理的和可維護的軟件構件,它支持特定的數據。資源可以通過名詞(noun)來定義,比如“醫生的預約”就描述了資源提供的數據。某一資源也可以和其他資源相關聯并為它們提供引用(鏈接)。實際上,一個資源就類似于一個對象[6],不過它是帶有預定義(CRUD)接口語義的對象。

      REST 中的語義基于 HTTP 操作集,如下所示[5]

    • createResource——創建一個新的資源(以及相應的唯一標示)– PUT
    • getResourceRepresentation——獲取資源信息– GET
    • deleteResource ——刪除資源(可選地包括相關聯的資源)– DELETE(只是引用的資源),POST(當需要刪除相關聯的資源時使用)
    • modifyResource——更改資源— POST
    • getMetaInforatmion——取得資源元數據信息—HEAD

      資源通過兩部分定義:資源 URL 和資源所提供的所有操作上定義的輸入/輸出參數[7]。這和服務不同,服務的方法之間是完全獨立,并且能夠以獨立端點(endpoints)的方式部署,而資源上的方法遵循 OO 語義,這意味著所有的方法(除createResource以外)都必須依附于底層的某個資源(同一個 URL)。

      資源和服務之間的根本差異

      基于上述對資源和服務的定義,憑直覺它們顯然是不同的。我們先繼續深究這些差別,然后再討論它們是如何對最終架構產生影響的。

      正如文獻[6]中描述的:

    REST 不僅不是面向服務的,相反,面向服務和 REST 風馬牛不相及

      文獻[7]中進一步闡明了二者之間的區別:

    如果把 WS-*比作是互聯網世界的 RPC,那么 REST 就是互聯網世界的數據庫管理系統(DBMS)……傳 統的基于 SOA 的集成表現了不同軟件構件之間通過各種過程或方法進行交互。REST 有效地將每個軟件構件看作一組數據庫表,而這些構件之間使用 SELECT, INSERT, UPDATE 和 DELETE 來通信。(或如你所想的使用 GET, PUT, POST, DELETE)。那業務邏輯放在哪里呢?在存儲過程中?不太對,其實在觸發器中。

      這里我們用 J2EE 打個稍微不太恰當的比方。我們把服務想象成無狀態會話 bean,而資源想象成實體 bean。

      服務(或會話 beans)作為控制器控制執行所需的操作,不管底層是哪個資源。打個比方,某個支出賬戶服務可能會用到賬戶 ID、支出金額和支出所需賬戶。這樣的服務可以支出任何現有賬戶。

      資源(或實體 bean)充當數據訪問機制,其面對給定數據類型的某一實例。比如,為了從某一賬戶支出,需要先找到這一賬戶相關的信息,然后才能更新它,從而向所需賬戶 進行支出。另外提醒一下,與能實現任意所需的方法的實體 bean 不同的是,一個 REST 資源只有一個更改資源的方法。這意味著真實的業務操作——支出——只能編碼成消息請求的一部分。

      區別引出的結論

      綜上所述,不可能使用本真 REST 來構建 SOA 系統。構建系統可以,但一定不是 SOA。兩者都可以從與業務一致的分解入手,但是由于各自使用截然不同的分解方法,它們最終得到的也是基于不同組件和連接器的完全不同的架構風格[8]

      僅僅因為它們都試圖解決同一個問題——業務與 IT 對齊,并且都基于業務驅動的分解,并不能表明最終的架構風格也是一樣的。

      另一個問題在于能否可能使用本真 REST 來構建一個完整的系統。鑒于上述理由,這個問題等價于能否可能只使用數據庫或實體 bean 來構建一個完整的系統。當然你可以了,但是需要以存儲過程(重寫方法的本意)的方式增加處理代碼,或者觸發器(完成基于數據變化的后置處理)。這同樣適用 于本真 REST 實現—你只有通過改變 modifyResource 方法的本意(通常使用命令行模式)來實現不止數據更新這個方法。

      因此,某個基于 REST 的實現和本真 REST 是大相徑庭的;一般來說其包含了至少一些 REST Web 服務的元素。那么 REST Web 服務是什么呢?

      REST Web 服務

      REST Web 服務方法是指單純使用 REST 技術作為通信手段來構建 SOA 的一種方法。在這種情況下,服務由 SOA 風格的分解來定義,而基于 REST 的 Web 服務[9]作為通信。

      雖然一般也被稱為 REST,這種方法其實和本真 REST 沒有一點關系,倒是和 POX(plain old XML over HTTP)很類似,不過與 POX 不同的是,它不僅支持 XML,還支持其他數據類型,比如 JSON(JavaScript Object Notation)、ATOM、二進制數據塊。而且,它不像 POX 那樣通常只基于 GET 和 PUT,它基于更多的 HTTP 方法。

      歸功于 Web 的優勢和 Ajax 技術的遍地開花,使用 JSON 逐漸變成主流的方法;大部分流行的瀏覽器都內置對 JSON 支持。由于在 JavaScript 中處理 XML(尤其是帶有很多命名空間)并不是一件容易的事,所以,Web 實現使用基于 JSON 的 REST Web 服務要容易的多。面向 Web 交互的 REST Web 服務的擴增導致了這些技術的日益流行和廣泛傳播。

      真正的差異是什么?

      描述 SOAP 和 REST 區別的出版刊物通常會指出如下 REST Web 服務的優點,比如[11]

    • 輕量級——無需太多額外的 XML 標記
    • 人工可讀的結果集
    • 易于構建——無需工具支持

      雖然這些區別很重要(我隨后會再詳細討論),但是 SOAP 和 REST 最主要的區別在于 REST 是直接實現于 HTTP 協議之上,而 SOAP 引人了一個抽象層(SOAP 消息傳遞),這可以在任何傳輸協議之上實現。標準化 SOAP 綁定目前存在于 HTTP、SMTP 和 JMS 之上,而非標準化綁定已經在其他一些協議解決方案實現了。這層額外的抽象層(提供協議和基于 SOAP 實現之間的解耦)是造成 SOAP 和 REST Web 服務區別的根源。

      對于這一抽象層的看法很大程度上取決于不同的人。REST 陣營認為它是過度設計的產物,并聲稱沒有提供任何實際價值。他們聲稱 HTTP 已經提供了服務交互實現必需的所有特點。而 SOAP 陣營,從另一方面,爭辯道 HTTP 并不是服務交互(尤其在企業內部)通常所需的唯一協議,而設計一個方便的、可擴展[10]的抽象層對構建健壯的、功能豐富的服務交互是很有必要的。

      雖然兩種觀點都有其可取之處,但我認為把 SOA 實現限制到單一協議,即 HTTP,實際操作起來不太可行。誠然,HTTP 是無處不在,并且其使用方法一般也無需投資額外的基礎設施,但是 HTTP 是不可靠的(HTTP-R沒有廣泛被采用)、同步的(產生了瞬時的耦合)[11]、而且也沒有事務語義等等。

      再者,就算認為 HTTP 是在實現中使用的唯一協議,也可以非常方便的利用 SOAP 信封把業務信息(SOAP 消息體)和基礎設施信息或附加信息(SOAP 消息頭)從 SOAP 消息中隔離。總的來說,如果你本來的實現并不需要任何基礎設施或附加數據,整個 SOAP 信封的開銷是很少的——只需兩個標簽,而且對必要時添加數據提供了明確定義的方法。

      所以,從各個方面來看,以數據信封的方式將業務信息和基礎設施關注分離是很強大的模式,甚至 REST Web 服務實現也常常使用這種方法。至于是否使用標準的 SOAP 還是定制化信封[12]模式要根據具體實現而定。

      其他關鍵不同點

      我們花點時間來討論一下其他一些常常被發表刊物引用的關于 SOAP 和 REST Web 服務的不同點。

      簡單化

      一個普遍的觀點是 REST 要比 SOAP 簡單得多。照這個觀點,REST 簡單的根源基于一個事實:REST 不需要 WSDL 或任何接口定義。至少可以認為這種論調有點天真。無論哪種用于服務消費者和提供者之間通信的技術,都必須在語法和其消息交互(接口)[13]的語義上達成一致。這意味著就 REST 而言,下面兩個方法有一個是可能的:

    • 以文本方式定義一個接口,并基于接口文檔描述中的通用接口定義來“手工地”編寫數據的編碼/解碼。雖然這種方法常被 REST 擁躉所推崇,其接口包含的元素很少超過 10 到 15 個,但這不是典型的粗粒度 REST 服務。而且,這種方法很容易出錯,所以,大部分可行的 REST 框架都遺棄該方法而使用下面的方法。
    • 在 XSD 的層次定義接口,基于流行框架(比如,面向 XML 的 JAXB 或 Castor,面向 JSON 負載的 Jackson)產生數據的編碼/解碼。這種方法效果上就是 WSDL 的簡約版,并且需要的工作量和基于 SOAP 實現差不多一樣。事實上,完全相同的方法經常被用于基于 SOAP 的實現,設計一個單獨接口和服務執行的命令模式。WSDL2.0 和/或 WADL for REST 就是對該方法的擴展。

      另一個 SOAP 常常被抱怨的就是復雜的 WS*標準集。雖然不存在一個單獨的規范來羅列這些關鍵的 WS*標準集以及其彼此的關系,但對大部分服務交互用例還是存在一個標準的。就算如此,選擇一個適當的 WS*標準和其用法可能也需要一些額外理解和實現時間,但是:

    在 REST 和 SOA 之戰中爭論簡單化還是標準化是荒唐的,因為沒有標準支持的簡單只能有害于成本和應用的可管理性。

      所以,除了那些簡單到極點的例子之外,如“溫度轉換器”,REST 并不比 SOAP 簡單多少。

      輕量級

      另一個眾多 REST 擁躉宣揚 REST 是 SOAP 的一種取代的原因是,實際上的 REST 請求和響應消息都較短。這主要基于兩個原因:

    • SOAP 需要一層 XML 包裝器來包裝所有的請求和響應消息,這會增加消息的大小。這話沒錯,但重點不是包裝器增加了多少字節,而是它創建在整個負載中的比例。因為包裝器的大小是 固定的,其所占比例隨著消息的不斷變大而變小,最終可以忽略不計。考慮到一般服務都是相當粗粒度的,請求和回復消息的大小也是相當大的,所以 SOAP 信封的負載不太會成為大問題。
    • SOAP 是基于 XML 的消息傳輸,而 XML 使用冗余的編碼。REST,在這方面,提供了更輕量級的消息傳輸替代方案——JSON[14]。這話也對,但利用消息傳輸優化機制(MTOM),大部分 SOAP 框架都支持,可以把消息拆分成多個小的基于 XML 的 SOAP 信封/頭/體部分,而附加的包含消息內容的部分可以編碼為任何 MIME 類型,包括 JSON 和二進制流等。

      雖然理論上講,REST 要比 SOAP 輕量級,但實際上,利用一些高級 SOAP 設計技術,真正使用中的 SOAP 和 REST 消息大小的差別是很小的。

      易于構建 – 無需工具支持

      因為 REST 基于 HTTP,其擁躉認為,我們可以使用熟稔的技術,比如 Java servlet API 和 Java HTTP 支持來編寫 REST 服務的實現端和客戶端,而無需任何特定工具的幫助。這可以說是對的,但前提是你想要“手工”實現構建輸入/輸出消息和數據編組。SOAP Web 服務也可以實現同樣的工作。然而,大家很少希望編寫這種樣例代碼,結果還是會使用工具,SOAP 和 REST 都是。

      結論

      REST 既適用于使用 ROA(本真 REST 方法)的系統設計,也適用于使用 REST 技術(REST Web 服務)的 SOA 設計實現。雖然兩種方法都有其優勢,但都沒有改變最難的部分——定義和企業業務模型一致的業務服務/資源。有些情況的確兩種都適合,但歸根到底這完全是兩 種不同的風格。

      關于作者

      Boris Lublinsky是 NAVTEQ 公司的首席架構師,在這家公司中他的工作是為大型數據管理及處理、SOA 定義架構愿景,并且實施各種 NAVTEQ 的項目。他還是 InfoQ 的 SOA 編輯, OASIS 的 SOA RA 工作組的參與者。Boris 是一位作者,還經常發表演講,他最新的一本書是《Applied SOA》

      致謝

      我要謝謝我 NAVTEQ 的同事,尤其是 Jeffrey Herr 在我撰寫這篇文章時提供的幫助。也要感謝 Stefan Tilkov 和 Kevin T. Smith 提供的有趣反饋(多數是負面的),這些反饋有助于文章的改進。

      參考

    1. Cesare Pautasso,Olaf Zimmermann,Frank Leymann 著《RESTful Web Services vs. “Big” Web Services: Making the Right Architectural Decision》
    2. Boris Lublinsky 著《Defining SOA as an architectural style
    3.  面向資源的架構
    4. Martin Fowler Richardson 著《Maturity Model: steps toward the glory of REST
    5. 面向資源的架構與 REST
    6. Dhananjay Nene 的博文“Service oriented REST architecture is an oxymoron
    7. Dhananjay Nene,“REST is the DBMS of the Internet ”。
    8. Dhananjay Nene,“Musings on REST
    9. J?rgen Thelin,“A Comparison of Service-oriented, Resource-oriented, and Object-oriented Architecture Styles
    10. Richard Hubert 著《Convergent Architecture: Building Model Driven J2EE Systems with UML》,Wiley,2011,ISBN:0471105600
    11. Arun Gandhi, “SOAP vs. REST – The Best WebService”。
    12. 請參見鏈接
    13. Lawrence Mandel,“Describe REST Web services with WSDL 2.0
    14. Web 應用描述語言
    15. Stefan Tilkov 訪談 Sanjiva Weerawarana,“Debunking REST/WS-* Myths
    16. Lori MacVittie,“SOAP vs REST: The war between simplicity and standards
    17. 請參見鏈接
    18. Mark Little,“A Comparison of JAX-RS Implementations”。

      說明

      [1]看這里,文中有個很好的比喻。

      [2]這里我使用的這個詞語,從技術上其毫無意義,也不是指 REST,但在業界被廣泛使用,而有很多人也認為它就是 REST。

      [3]按照定義,資源可以是任何應該被直接呈現和訪問的組件。

      [4]這類服務常用的一種實現是基于“命令模式”。一個輸入文檔定義命令本身和用于執行命令的數據。

      [5]方法獨立源自于這樣一個事實:不同的方法可以執行同一數據——這里指的是無論是否被服務暴露都存在的企業數據,而不是在 OO 中的針對特定數據的某對象實例。

      [6]例如,在文獻[4]中對 OO 和 REST 做了直接類比。

      [7]許多 REST 倡導者聲稱后者是沒有必要的。我們在文章后面會再回到這個問題上。

      [8]架構風格就像面向于不同軟件系統之間結構和連接的“設計模式”。文獻[10]提供了關于架構風格的一個比較完整的定義,“架構風格是指一組有相同原則和屬性的架構”

      [9]另一個在業界被普遍亂用的名稱——根據定義,Web 服務就是 SOAP 消息。

      [10]所有的 WS*實現都重度依賴 SOAP,尤其是 SOAP 頭。

      [11]你總是可以在 HTTP 上實現異步消息機制,但是需要額外的抽象層,比如 SOAP 就在其上使用了 WS-Addressing。

      [12] 許多 REST 倡導者認為 HTTP 已經有了一組標準的消息頭,因此 SOAP 消息頭完全沒有必要。這里的問題在于一組預定義好的 HTTP 頭固然有其良好定義的語義,但任何應用特定數據必需一個自定義 HTTP 消息頭,這和自定義 SOAP 消息頭的復雜度相同。

      [13]一個有趣例子是,在很多 JAX-RS 實現中客戶端 API,其接口往往是一個 java 接口——許多對多語言的支持。

      [14]簡單通常意味著高價——所以,要試圖通過無需手動編碼對象類型而用 JSON 消息實現多態

      查看英文原文:Is REST the future for SOA?

    來自: InfoQ

    相似問題

    相關經驗

    相關資訊

    相關文檔

  • sesese色