WebService 之 REST vs SOAP

在SOA的基礎技術實現方式中WebService佔據了很重要的地位,一般咱們提到WebService第一想法就是SOAP消息在各類傳輸協議上交互。近幾年REST的思想伴隨着SOA逐漸被你們接受,同時各大網站不斷開放API提供給開發者,也激起了REST風格WebService的熱潮。php

       ASF的最新需求就是可能須要實現REST風格的WebService集成,所以不得很差好的去看看REST的真正思想含義以及當前各大網站的設計方式。後面所要表述的也是我這個初學者的一些見解和觀點,拋磚引玉,但願在我將REST融入到ASF以前可以得到更多的反饋和意見。
 
SOAP
       什麼是SOAP,我想不用多說,google一把滿眼都是。其實SOAP最先是針對RPC的一種解決方案,簡單對象訪問協議,很輕量,同時做爲應用協議能夠基於多種傳輸協議來傳遞消息(Http,SMTP等)。可是隨着SOAP做爲WebService的普遍應用,不斷地增長附加的內容,使得如今開發人員以爲SOAP很重,使用門檻很高。在SOAP後續的發展過程當中,WS-*一系列協議的制定,增長了SOAP的成熟度,也給SOAP增長了負擔。
 
REST
       REST其實並非什麼協議也不是什麼標準,而是將Http協議的設計初衷做了詮釋,在Http協議被普遍利用的今天,愈來愈多的是將其做爲傳輸協議,而非原先設計者所考慮的應用協議。SOAP類型的WebService就是最好的例子,SOAP消息徹底就是將Http協議做爲消息承載,以致於對於Http協議中的各類參數(例如編碼,錯誤碼等)都置之不顧。其實,最輕量級的應用協議就是Http協議。Http協議所抽象的get,post,put,delete就比如數據庫中最基本的增刪改查,而互聯網上的各類資源就比如數據庫中的記錄(可能這麼比喻不是很好),對於各類資源的操做最後老是能抽象成爲這四種基本操做,在定義了定位資源的規則之後,對於資源的操做經過標準的Http協議就能夠實現,開發者也會受益於這種輕量級的協議。
       本身理解的將REST的思想歸結如下有以下幾個關鍵點:
      
1.面向資源的接口設計
全部的接口設計都是針對資源來設計的,也就很相似於咱們的面向對象和麪向過程的設計區別,只不過如今將網絡上的操做實體都做爲資源來看待,同時URI的設計也是體現了對於資源的定位設計。後面會提到有一些網站的API設計說是REST設計,實際上是RPC-REST的混合體,並不是是REST的思想。
 
       2.抽象操做爲基礎的CRUD
       這點很簡單,Http中的get,put,post,delete分別對應了read,update,create,delete四種操做,若是僅僅是做爲對於資源的操做,抽象成爲這四種已經足夠了,可是對於如今的一些複雜的業務服務接口設計,可能這樣的抽象未必可以知足。其實這也在後面的幾個網站的API設計中暴露了這樣的問題,若是要徹底按照REST的思想來設計,那麼適用的環境將會有限制,而非放之四海皆準的。      
 
       3.Http是應用協議而非傳輸協議
       這點在後面各大網站的API分析中有很明顯的體現,其實有些網站已經走到了SOAP的老路上,說是REST的理念設計,實際上是做了一套私有的SOAP協議,所以稱之爲REST風格的自定義SOAP協議。
 
4.無狀態,自包含
這點其實不只僅是對於REST來講的,做爲接口設計都須要可以作到這點,也是做爲可擴展和高效性的最基本的保證,就算是使用SOAP的WebService也是同樣。
 
 
REST vs SOAP
成熟度:
SOAP雖然發展到如今已經脫離了初衷,可是對於異構環境服務發佈和調用,以及廠商的支持都已經達到了較爲成熟的狀況。不一樣平臺,開發語言之間經過SOAP來交互的web service都可以較好的互通(在部分複雜和特殊的參數和返回對象解析上,協議沒有做很細緻的規定,致使仍是須要做部分修正)
REST國外不少大網站都發布了本身的開發API,不少都提供了SOAP和REST兩種Web Service,根據調查部分網站的REST風格的使用狀況要高於SOAP。可是因爲REST只是一種基於Http協議實現資源操做的思想,所以各個網站的REST實現都自有一套,在後面會講訴各個大網站的REST API的風格。也正是由於這種各自實現的狀況,在性能和可用性上會大大高於SOAP發佈的web service,但統一通用方面遠遠不及SOAP。因爲這些大網站的SP每每專一於此網站的API開發,所以通用性要求不高。
ASF上考慮發佈REST風格的Web Service,能夠參考幾大網站的設計(兄弟公司的方案就是參考了相似於flickr的設計模式),可是因爲沒有相似於SOAP的權威性協議做爲規範,REST實現的各類協議僅僅只能算是私有協議,固然須要遵循REST的思想,可是這樣細節方面有太多沒有約束的地方。REST往後的發展所走向規範也會直接影響到這部分的設計是否可以有很好的生命力。
總的來講SOAP在成熟度上優於REST。
 
效率和易用性:
       SOAP協議對於消息體和消息頭都有定義,同時消息頭的可擴展性爲各類互聯網的標準提供了擴展的基礎,WS-*系列就是較爲成功的規範。可是也因爲SOAP因爲各類需求不斷擴充其自己協議的內容,致使在SOAP處理方面的性能有所降低。同時在易用性方面以及學習成本上也有所增長。
       REST被人們的重視,其實很大一方面也是由於其高效以及簡潔易用的特性。這種高效一方面源於其面向資源接口設計以及操做抽象簡化了開發者的不良設計,同時也最大限度的利用了Http最初的應用協議設計理念。同時,在我看來REST還有一個很吸引開發者的就是可以很好的融合當前Web2.0的不少前端技術來提升開發效率。例如不少大型網站開放的REST風格的API都會有多種返回形式,除了傳統的xml做爲數據承載,還有(JSON,RSS,ATOM)等形式,這對不少網站前端開發人員來講就可以很好的mashup各類資源信息。
       所以在效率和易用性上來講,REST更勝一籌。
 
安全性:
       這點其實能夠放入到成熟度中,不過在當前的互聯網應用和平臺開發設計過程當中,安全已經被提到了很高的高度,特別是做爲外部接口給第三方調用,安全性可能會高過業務邏輯自己。
       SOAP在安全方面是經過使用XML-Security和XML-Signature兩個規範組成了WS-Security來實現安全控制的,當前已經獲得了各個廠商的支持,.net ,php ,java 都已經對其有了很好的支持(雖然在一些細節上仍是有不兼容的問題,可是互通基本上是能夠的)。
       REST沒有任何規範對於安全方面做說明,同時如今開放REST風格API的網站主要分紅兩種,一種是自定義了安全信息封裝在消息中(其實這和SOAP沒有什麼區別),另一種就是靠硬件SSL來保障,可是這隻可以保證點到點的安全,若是是須要多點傳輸的話SSL就無能爲力了。安全這塊其實也是一個很大的問題,今年在BEA峯會上看到有演示採用SAML2實現的網站間SSO,實際上是直接採用了XML-Security和XML-Signature,效率看起來也不是很高。將來REST規範化和通用化過程當中的安全是否也會採用這兩種規範,是未知的,可是加入的越多,REST失去它高效性的優點越多。
 
應用設計與改造:
       咱們的系統要麼就是已經有了那些須要被髮布出去的服務,要麼就是剛剛設計好的服務,可是開發人員的傳統設計思想讓REST的形式被接受還須要一點時間。同時在資源型數據服務接口設計上來講按照REST的思想來設計相對來講要容易一些,而對於一些複雜的服務接口來講,可能強要去按照REST的風格來設計會有些牽強。這一點其實能夠看看各大網站的接口就能夠知道,不少網站還要傳入function的名稱做爲參數,這就明顯已經違背了REST自己的設計思路。
       而SOAP自己就是面向RPC來設計的,開發人員十分容易接受,因此不存在什麼適應的過程。
 
總的來講,其實仍是一個老觀念,適合的纔是最好的
       技術沒有好壞,只有是否是合適,一種好的技術和思想被誤用了,那麼就會獲得反效果。REST和SOAP各自都有本身的優勢,同時若是在一些場景下若是去改造REST,其實就會走向SOAP(例如安全)。
       REST對於資源型服務接口來講很合適,同時特別適合對於效率要求很高,可是對於安全要求不高的場景。而SOAP的成熟性能夠給須要提供給多開發語言的,對於安全性要求較高的接口設計帶來便利。因此我以爲純粹說什麼設計模式將會佔據主導地位沒有什麼意義,關鍵仍是看應用場景。
       同時很重要一點就是不要扭曲了REST如今不少網站都跟風去開發REST風格的接口,其實都是在學其形,不知其心,最後弄得不三不四,性能上不去,安全又保證不了,徒有一個看似象摸象樣的皮囊。
 
REST設計的幾種形式
參看了幾個大型網站的REST風格的API設計,這裏作一下大體的說明:
 
FaceBook:
 
請求消息:
       在URI設計上採起了相似於REST的風格。例如對於friends的獲取,就定義爲friends.get,前面部分做爲資源定義,後面是具體的操做,其餘的API也是相似,資源+操做,所以就算使用http的get方法均可能做了update的操做,其實已經違背了REST的思想,可是說到,其實那麼複雜的業務接口設計下,要經過RUCD來抽象全部的接口基本是不實際的。在URI定義好之後,還有詳細的參數定義,包括類型以及是否必選。
 
響應消息:
       有多種方式,XML,JSON。XML有XSD做爲參考。有點相似於沒有Head的SOAP,只不過這裏將原來能夠定義在WSDL中的XSD抽取出來了。
 
Flickr:
       請求消息:
       http://api.flickr.com/services/rest/?method=flickr.test.echo&name=value
       這裏就能夠很明顯看出它所定製的REST請求其實和RPC沒有什麼太大的區別。
      
       消息返回:
正確處理返回
<?xml version="1.0" encoding="utf-8" ?>
<rsp stat="ok">
         [xml-payload-here]
</rsp>
錯誤處理返回
<?xml version="1.0" encoding="utf-8" ?>
<rsp stat="fail">
         <err code="[error-code]" msg="[error-message]" />
</rsp>
       根據返回能夠看出已經違背了REST的思想,仍是把Http協議做爲傳輸承載協議,並無真正意義上使用Http協議做爲資源訪問和操做協議。
       總的來講,只是形式上去模仿REST,本身搞了一套私有協議。
 
Ebay
       請求消息:
       採用xml做爲承載,相似於SOAP,不過去除SOAP消息的封裝和包頭,同時在請求中附加了認證和警告級別等附加信息。
       消息返回:
       相似於SOAP消息,不過刪除了SOAP的封裝和包頭,同時在返回結構中增長了消息處理結果以及版本等附加信息。
       這個很相似於當前Axis2框架的作法,將SOAP精簡,同時根據自身需求豐富了安全,事務等協議內容。
 
Yahoo Maps
       請求消息:
       採用REST推薦的方式,URI+Parameters。
       返回消息:
<?xml version="1.0" encoding="UTF-8"?>
<ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:yahoo:maps"
xsi:schemaLocation="urn:yahoo:maps http://local.yahooapis.com/MapsService/V1/GeocodeResponse.xsd">
 <Result precision="address">
    <Latitude>37.416384</Latitude>
    <Longitude>-122.024853</Longitude>
    <Address>701 FIRST AVE</Address>
    <City>SUNNYVALE</City>
    <State>CA</State>
    <Zip>94089-1019</Zip>
    <Country>US</Country>
 </Result>
</ResultSet>
SOAP的精簡xml返回,其餘信息,例如出錯碼等信息由Http協議頭來承載。
 
YouTube
請求消息:
能夠看到對於資源操做的URI定義也是參數的一部分。
返回消息:
<?xml version="1.0" encoding="utf-8"?>
<ut_response status="ok">
    <user_profile>
        <first_name>YouTube</first_name>
        <last_name>User</last_name>
        <about_me>YouTube rocks!!</about_me>
        <age>30</age>
        <video_upload_count>7</video_upload_count>
    </user_profile>
</ut_response>
       自定義的類SOAP消息。
 
Amazon
       請求消息:
       https://Amazon FPS web service end point/?AWSAccessKeyId=Your AWSAccessKeyId
      &Timestamp=[Current timestamp] &Signature=[Signature calculated from hash of Action and Timestamp]
      &SignatureVersion=[Signature calculated from hash of Action and Timestamp]
      &Version=[Version of the WSDL specified in YYYY-MM-DD format] &Action=[Name of the API]
      &parameter1=[Value of the API parameter1] &parameter2=[Value of the API parameter2]
      &...[API parameters and their values]
       返回消息:
       相似於SOAP的自有協議,消息體中包含了消息狀態等附加信息。
 
總結:
       看了上面那麼多網站的設計,總結一下主要有這麼幾種設計方式。
 
請求消息設計:
1. 基本符合REST標準方式:資源URI定義(資源.操做)+參數。這類設計若是濫用get去處理其餘類型的操做,那麼和2無異。
2. REST風格非REST思想:資源URI定義+參數(包含操做方法名)。其實就是RPC的REST跟風。
3. 相似於SOAP消息,自定義協議,以xml做爲承載。(可擴展,例如鑑權,訪問控制等),不過那就比如本身定義了一套SOAP和SOAP extends。大型的有實力的網站有的採起此種作法。
 
響應消息設計:
1.       REST標準方式,將Resource State傳輸返回給客戶端,Http消息做爲應用協議而非傳輸協議
2.       以XML做爲消息承載體,Http做爲消息傳輸協議,處理狀態自包含。
3.       自定義消息格式,相似於SOAP,提供可擴展部分。
 
做爲遵循REST的理念來看個人選擇是響應1和請求1的設計。
 
 
REST和ASF的集成
ASF要集成REST就如今來看有兩種比較合適的方法。
一.就是採用Axis2的REST實現,這種方式的好處就是開發週期短,容易集成,可是請求和響應的格式沒法改變,資源URI設計受限,Axis2的REST其實就是將SOAP消息精簡,請求的時候刪除了SOAP的頭,響應的時候僅僅返回資源信息,若是提供xsd就能夠被各類客戶端所解析。並不是真正的REST。
二.就是採用Restlet開源框架,將Restlet開源框架集成到ASF中,因爲Restlet自己就是可內嵌的應用框架,所以集成不成問題,同時Restlet框架只是API結構框架,所以實現和定義徹底分開,集成Restlet之後能夠本身實現其中的解析引擎也能夠採用默認提供的引擎,同時對於內嵌Jetty等多種開源項目的支持,將更多優點融入到了Rest中。看了一下國內也有不少朋友已經關注Restlet開源項目,看了它的架構設計,我的以爲仍是比較靈活和緊湊的。
 
題外話
       在寫這篇文章之前寫了一篇調研報告羣發給各個架構師們參考,期待反饋。下午正好和咱們的首席架構師聊了一下子。其實我和他的感受是同樣的,REST是否真的在咱們現有的服務框架中須要集成,理解了REST的思想再去看應用場景,那麼能夠發現若是要徹底遵循REST的設計理念來設計接口的話,那麼強要去改變現有已經存在的或者還未開發的接口就會落入爲了技術而技術,爲了潮流而跟風的近地。固然並不否定REST的好,其實咱們兄弟公司的一些業務場景有部分的接口十分合適這類設計,面向資源,高效,簡潔,易用都可以體現出它的價值。咱們將會和咱們的兄弟公司合做,也會參考他們的設計理念,在參考當前各個網站的實現狀況下,部分的採用這類形式的發佈,提供給第三方的ISV,無疑是我如今把REST融入到ASF中最好的理由。
       有了需求去作纔不會陷入爲了技術而技術,畢竟技術是由商業價值驅動的,一樣社會上充斥着各類技術的鼓吹,若是稍不留神就會陷入跟風的潮流中。
相關文章
相關標籤/搜索