隨著Restful的流行,soap似乎有點貴族落寞了。下面我們先詳細分析一下他們的各自的特點。
Restful 簡介
REST(Representational State Transfer)是 Roy Fielding 提出的一個描述互聯絡統架構風格的名詞。為什麼稱為 REST?Web 本質上由各種各樣的資源群組成,資源由 URI 唯一標識。瀏覽器(或者任何其它類似於瀏覽器的應用程式)將展示出該資源的一種表現方式,或者一種表現狀態。如果使用者在該頁面中定向到指向其它資源的連結,則將訪問該資源,並表現出它的狀態。這意味著用戶端應用程式隨著每個資源表現狀態的不同而發生狀態轉移,也即所謂 REST。
關於 REST 本身,本文就不再這裡過多地討論,讀者可以參考 developerWorks 上其它介紹 REST 的文章。本文的重點在於通過 REST 與 SOAP Web 服務的對比,協助讀者更深刻理解 REST 架構風格的特點,優勢。
Restful 設計
我們將採用遵循 REST 設計原則的 ROA(Resource-Oriented Architecture,面向資源的體系架構)進行設計。ROA 是什嗎?簡單點說,ROA 是一種把實際問題轉換成 REST 式 Web 服務的方法,它使得 URI、HTTP 和 XML 具有跟其他 Web 應用程式一樣的工作方式。
在使用 ROA 進行設計時,我們需要把真實的應用需求轉化成 ROA 中的資源,基本上遵循以下的步驟:
- 分析應用需求中的資料集。
- 映射資料集到 ROA 中的資源。
- 對於每一資源,命名它的 URI。
- 為每一資源設計其 Representations。
- 用 hypermedia links 表述資源間的聯絡。
Restful Web服務架構
SOAP架構相信大家已經很熟了,即使不是真正的很熟,但至少以前都用過吧。web service曾經流行一時。先看看它的架構
SOAP Web架構
可以看到,與 REST 架構相比,SOAP 架構圖明顯不同的是:所有的 SOAP 訊息發送都使用 HTTP POST 方法,並且所有 SOAP 訊息的 URI 都是一樣的,這是基於 SOAP 的 Web 服務的基本實踐特徵。
Restful Web服務 與 SOAP Web服務 對比
介面抽象
RESTful Web 服務使用標準的 HTTP 方法 (GET/PUT/POST/DELETE) 來抽象所有 Web 系統的服務能力,而不同的是,SOAP 應用都通過定義自己個人化的介面方法來抽象 Web 服務,這更像我們經常談到的 RPC。例如本例中的 getUserList 與 getUserByName 方法。
RESTful Web 服務使用標準的 HTTP 方法優勢,從大的方面來講:標準化的 HTTP 操作方法,結合其他的標準化技術,如 URI,HTML,XML 等,將會極大提高系統與系統之間整合的互操作能力。尤其在 Web 應用程式領域,RESTful Web 服務所表達的這種抽象能力更加貼近 Web 本身的工作方式,也更加自然。
同時,使用標準 HTTP 方法實現的 RRESTful Web 服務也帶來了 HTTP 方法本身的一些優勢:
HTTP 協議從本質上說是一種無狀態的協議,用戶端發出的 HTTP 要求之間可以相互隔離,不存在相互的狀態依賴。基於 HTTP 的 ROA,以非常自然的方式來實現無狀態服務請求處理邏輯。對於分布式的應用而言,任意給定的兩個服務要求 Request 1 與 Request 2, 由於它們之間並沒有相互之間的狀態依賴,就不需要對它們進行相互協作處理,其結果是:Request 1 與 Request 2 可以在任何的伺服器上執行,這樣的應用很容易在伺服器端支援Server Load Balancer (load-balance)。
- 安全操作與冪指相等特性(Safety /Idempotence)
HTTP 的 GET、HEAD 請求本質上應該是安全的調用,即:GET、HEAD 調用不會有任何的副作用,不會造成伺服器端狀態的改變。對於伺服器來說,用戶端對某一 URI 做 n 次的 GET、HAED 調用,其狀態與沒有做調用是一樣的,不會發生任何的改變。
HTTP 的 PUT、DELTE 調用,具有冪指相等特性 , 即:用戶端對某一 URI 做 n 次的 PUT、DELTE 調用,其效果與做一次的調用是一樣的。HTTP 的 GET、HEAD 方法也具有冪指相等特性。
HTTP 這些標準方法在原則上保證你的分布式系統具有這些特性,以協助構建更加健壯的分布式系統。
安全控制
為了說明問題,基於上面的線上使用者管理系統,我們給定以下情境:
參考一開始我們給出的使用案例圖,對於用戶端 Client2,我們只希望它能以唯讀方式訪問 User 和 User List 資源,而 Client1 具有訪問所有資源的所有許可權。
如何做這樣的安全控制?
通行的做法是:所有從用戶端 Client2 發出的 HTTP 要求都經過Proxy 伺服器 (Proxy Server)。Proxy 伺服器制定安全性原則:所有經過該代理的訪問 User 和 User List 資源的請求只具有讀取許可權,即:允許 GET/HEAD 操作,而像具有寫入權限的 PUT/DELTE 是不被允許的。
如果對於 REST,我們看看這樣的安全性原則是如何部署的。如所示:
一般Proxy 伺服器的實現根據 (URI, HTTP Method) 兩元組來決定 HTTP 要求的安全合法性。
當發現類似於(http://localhost:8182/v1/users/{username},DELETE)這樣的請求時,予以拒絕。
對於 SOAP,如果我們想藉助於既有的Proxy 伺服器進行安全控制,會比較尷尬,如:
所有的 SOAP 訊息經過Proxy 伺服器,只能看到(http://localhost:8182/v1/soap/servlet/messagerouter, HTTP POST)這樣的資訊,如果Proxy 伺服器想知道當前的 HTTP 要求具體做的是什麼,必須對 SOAP 的訊息體解碼,這樣的話,意味著要求第三方的Proxy 伺服器需要理解當前的 SOAP 訊息語義,而這種 SOAP 應用與Proxy 伺服器之間的緊耦合關係是不合理的。
關於緩衝
眾所周知,對於基於網路的分布式應用,網路傳輸是一個影響應用效能的重要因素。如何使用緩衝來節省網路傳輸帶來的開銷,這是每一個構建分布式網路應用的開發人員必須考慮的問題。
HTTP 協議帶條件的 HTTP GET 請求 (Conditional GET) 被設計用來節省用戶端與伺服器之間網路傳輸帶來的開銷,這也給用戶端實現 Cache 機制 ( 包括在用戶端與伺服器之間的任何代理 ) 提供了可能。HTTP 協議通過 HTTP HEADER 域:If-Modified-Since/Last- Modified,If-None-Match/ETag 實現帶條件的 GET 請求。
REST 的應用可以充分地挖掘 HTTP 協議對緩衝支援的能力。當用戶端第一次發送 HTTP GET 請求給伺服器獲得內容後,該內容可能被快取服務器 (Cache Server) 緩衝。當下一次用戶端請求同樣的資源時,緩衝可以直接給出響應,而不需要請求遠端伺服器獲得。而這一切對用戶端來說都是透明的。
而對於 SOAP,情況又是怎樣的呢?
使用 HTTP 協議的 SOAP,由於其設計原則上並不像 REST 那樣強調與 Web 的工作方式相一致,所以,基於 SOAP 應用很難充分發揮 HTTP 本身的緩衝能力。
兩個因素決定了基於 SOAP 應用的緩衝機制要遠比 REST 複雜:
其一、所有經過快取服務器的 SOAP 訊息總是 HTTP POST,快取服務器如果不解碼 SOAP 訊息體,沒法知道該 HTTP 要求是否是想從伺服器獲得資料。
其二、SOAP 訊息所使用的 URI 總是指向 SOAP 的伺服器,如本文例子中的 http://localhost:8182/v1/soap/servlet/messagerouter,這並沒有表達真實的資源 URI,其結果是快取服務器根本不知道那個資源正在被請求,更不用談進行緩衝處理。
關於串連
在一個純的 SOAP 應用中,URI 本質上除了用來指示 SOAP 伺服器外,本身沒有任何意義。與 REST 的不同的是,無法通過 URI 驅動 SOAP 方法調用。例如在我們的例子中,當我們通過
getUserList SOAP 訊息獲得所有的使用者列表後,仍然無法通過既有的資訊得到某個具體的使用者資訊。唯一的方法只有通過 WSDL 的指示,通過調用 getUserByName 獲得,getUserList 與 getUserByName 是彼此孤立的。
而對於 REST,情況是完全不同的:通過 http://localhost:8182/v1/users URI 獲得使用者列表,然後再通過使用者列表中所提供的 LINK 屬性,例如
<link>http://localhost:8182/v1/users/tester</link>獲得 tester 使用者的使用者資訊。這樣的工作方式,非常類似於你在瀏覽器的某個頁面上點擊某個 hyperlink, 瀏覽器幫你自動定向到你想訪問的頁面,並不依賴任何第三方的資訊。
總結
典型的基於 SOAP 的 Web 服務以操作為中心,每個操作接受 XML 文檔作為輸入,提供 XML 文檔作為輸出。在本質上講,它們是 RPC 風格的。而在遵循 REST 原則的 ROA 應用中,服務是以資源為中心的,對每個資源的操作都是標準化的 HTTP 方法。
本文主要集中在以上的幾個方面,對 SOAP 與 REST 進行了對比,可以看到,基於 REST 構建的系統其系統的擴充能力要強於 SOAP,這可以體現在它的統一介面抽象、Proxy 伺服器支援、快取服務器支援等諸多方面。並且,伴隨著 Web Site as Web Services 演化的趨勢,基於 REST 設計和實現的簡單性和強擴充性,有理由相信,REST 將會成為 Web 服務的一個重要架構實踐領域。