RESTful 與 webservice

jopen 10年前發布 | 56K 次閱讀 RESTfull WEB服務/RPC/SOA

接口抽象

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 方法本身的一些優勢:

  • 無狀態性(Stateless)

    </li> </ul>

    HTTP 協議從本質上說是一種無狀態的協議,客戶端發出的 HTTP 請求之間可以相互隔離,不存在相互的狀態依賴。基于 HTTP 的 ROA,以非常自然的方式來實現無狀態服務請求處理邏輯。對于分布式的應用而言,任意給定的兩個服務請求 Request 1 與 Request 2, 由于它們之間并沒有相互之間的狀態依賴,就不需要對它們進行相互協作處理,其結果是:Request 1 與 Request 2 可以在任何的服務器上執行,這樣的應用很容易在服務器端支持負載平衡 (load-balance)。

    • 安全操作與冪指相等特性(Safety /Idempotence)

      </li> </ul>

      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 Server)。代理服務器制定安全策略:所有經過該代理的訪問 User 和 User List 資源的請求只具有讀取權限,即:允許 GET/HEAD 操作,而像具有寫權限的 PUT/DELTE 是不被允許的。

      如果對于 REST,我們看看這樣的安全策略是如何部署的。如下圖所示:


      圖 4. REST 與代理服務器 (Proxy Servers)
      RESTful 與 webservice 

      一般代理服務器的實現根據 (URI, HTTP Method) 兩元組來決定 HTTP 請求的安全合法性。

      當發現類似于(http://localhost:8182/v1/users/{username},DELETE)這樣的請求時,予以拒絕。

      對于 SOAP,如果我們想借助于既有的代理服務器進行安全控制,會比較尷尬,如下圖:


      圖 5. SOAP 與代理服務器 (Proxy Servers)
      RESTful 與 webservice 

      所有的 SOAP 消息經過代理服務器,只能看到(http://localhost:8182/v1/soap/servlet/messagerouter, HTTP POST)這樣的信息,如果代理服務器想知道當前的 HTTP 請求具體做的是什么,必須對 SOAP 的消息體解碼,這樣的話,意味著要求第三方的代理服務器需要理解當前的 SOAP 消息語義,而這種 SOAP 應用與代理服務器之間的緊耦合關系是不合理的。

      關于緩存

      眾所周知,對于基于網絡的分布式應用,網絡傳輸是一個影響應用性能的重要因素。如何使用緩存來節省網絡傳輸帶來的開銷,這是每一個構建分布式網絡應用的開發人員必須考慮的問題。

      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) 緩存。當下一次客戶端請求同樣的資源時,緩存可以直接給出響應,而不需要請求遠程的服務器獲得。而這一切對客戶端來說都是透明的。


      圖 6. REST 與緩存服務器 (Cache Server)
      RESTful 與 webservice 

      而對于 SOAP,情況又是怎樣的呢?

      使用 HTTP 協議的 SOAP,由于其設計原則上并不像 REST 那樣強調與 Web 的工作方式相一致,所以,基于 SOAP 應用很難充分發揮 HTTP 本身的緩存能力。


      圖 7. SOAP 與緩存服務器 (Cache Server)
      RESTful 與 webservice 

      兩個因素決定了基于 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,這可以體現在它的統一接口抽象、代理服務器支持、緩存服務器支持等諸多方面。并且,伴隨著 Web Site as Web Services 演進的趨勢,基于 REST 設計和實現的簡單性和強擴展性,有理由相信,REST 將會成為 Web 服務的一個重要架構實踐領域。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!