RESTful 真正意味著什麼?

oschina發表於2016-08-18

上個月,我在Skillsmatter參加了一個關於RESTful微服務快速進階的培訓課程。課程著重探討了REST API在web應用和微服務互動方面起到的作用。對我來說,這個課程給我最大的收穫是讓我更好地理解REST,以及它的優點和不足。

過去我大部分工作是在移動技術領域,也就是web API的呼叫端。我過去所呼叫的大部分API被認為是RESTful的,不過現在我對RESTful有了更深的理解,我敢說那些API裡有99%都算不上RESTful。

定義

REST是“呈現狀態轉移(REpresentational State Transfer)”的縮寫。或許可以這樣來定義它:一種API的架構風格,在客戶端和服務端之間通過呈現狀態的轉移來驅動應用狀態的演進。

約束

要讓應用RESTful化,需要遵循以下約束。遵循了這些約束的分散式系統,就會擁有如下非功能屬性:效能,伸縮性,易用性,擴充套件性,可見性,可移植性和可靠性。

CS模式

CS模式通過分離客戶端和伺服器端的關注點,讓客戶端不再關注資料的儲存問題,從而提高客戶端程式碼的可移植性。另一方面,伺服器端不再關注使用者介面和使用者狀態,從而變得更簡單,提高了伸縮性。伺服器端跟客戶端可以獨立開發,只要它們都遵守契約。

無狀態

客戶端上下文在多個請求之間是絕不會儲存在伺服器上的。每個請求必須包含必要的資訊。無狀態的伺服器通過快速釋放資源和簡化實現提高了可伸縮性。可靠性使得從區域性失敗中恢復變得容易。很明顯,監控系統不必通過考慮單個請求來判斷請求的性質。

無狀態伺服器的一個缺點是降低了網路效能,因為所有需要的資料必須在每次請求中傳送。

可快取

REST應用程式是web系統,因此客戶端和中間層可以快取響應。響應必須被定義為可快取或不可快取的,以防客戶端重複使用舊資料導致降低可靠性。如果快取中的陳舊資料與已生成的請求的資料顯著不同,則由伺服器處理請求。快取可以消除一些客戶端和伺服器之間的互動,這就提升了可伸縮性、效率和通過減少平均延遲達到的使用者可感知的效能。 

統一的介面

使用統一的介面降低了系統複雜度和耦合度,讓系統的不同部分可以獨立演化。稍後會解釋URI,資源和超媒體是如何通過生成標準介面來提升使用者互動可見性,降低系統複雜度,促進系統元件獨立演化的。但是我們需要在效率方面做出妥協,畢竟訊息是通過標準格式傳輸的,並不能滿足所有應用對訊息格式的要求。

分層的系統

分層系統通過約束元件的行為來降低系統複雜度,元件不能越過它們的媒介層去訪問其它層。通過元件的阻斷來保持層間的獨立性。遺留的元件可以被封裝成新的層,不讓舊的客戶端訪問。媒介層可以通過負載均衡來提升伸縮性。分層系統存在的主要不足,是它給資料處理增加了一些額外的開銷,增加了延遲,對使用者體驗有所影響。

按需編碼

REST允許客戶端通過下載執行指令碼來擴充套件它們的功能,簡化了客戶端,也提升了擴充套件性。但這同時也降低了可見性,所以這個約束不是必須遵循的。

元素

REST提供了以下幾種元素來構建無狀態,可伸縮的web API。

  • HTTP協議

  • 資源

  • URI

  • 超媒體

HTTP - 文字傳輸協議

REST一般使用HTTP作為它的傳輸協議,因為HTTP提供了一些很好用的特性,如HTTP動詞,狀態碼和頭部資訊。

HTTP動詞

HTTP並沒有定義很多動詞來描述web服務中可能出現的行為,它只用了一個標準動詞集合來處理各種相似情況,從而讓API變得更直觀。每個動詞通過兩種屬性的組合來滿足不同的場景需求。

  • 冪等性:操作可以被重複執行,就算在失敗以後。

  • 安全性:對客戶端來說操作不會產生副作用。

 

GET

用來從伺服器端讀取狀態。這個操作是安全的,所以它可以被執行很多次而不會對資料有任何影響,也就是說執行它一次跟執行十次是一樣的效果。從冪等性方面來看,多次請求跟單個請求總能得到相同的結果。

POST

一般用來在伺服器端建立某種狀態。這個操作不具備冪等性跟安全性,所以多次請求會在伺服器端建立多個資源。因為POST是不冪等的, 所以不應該被用來做跟金錢有關係的操作,試想一次失敗的請求如果被執行多次,那麼很可能轉賬或者支付也被執行了多次。

PUT

雖然它也可以被用來建立狀態,但主要還是用來在伺服器端更新狀態的。它是冪等的,但不安全,因為它會改變服務端的狀態。因為它的冪等性,PUT可以被用來處理跟金錢有關係的操作。

DELETE

用來在伺服器端刪除狀態。它也是冪等非安全的,因為它會移除服務端的狀態。它之所以是冪等的,是因為重複刪除一個狀態的結果是一樣。

響應狀態碼

HTTP在請求資源的響應裡提供了後設資料資訊,也就是狀態碼。它們是web平臺之所以能用來構建分散式系統的重要因素。它們被分為以下幾類:

  • 1xx —— 後設資料

  • 2xx —— 正確的響應

  • 3xx —— 重定向

  • 4xx —— 客戶端錯誤

  • 5xx —— 服務端錯誤

頭部資訊

HTTP在訊息頭部裡為請求響應提供了額外資訊。每個頭部由大小寫敏感的關鍵字和值組成,中間用冒號隔開。頭部資訊被分為以下幾類:

  • 一般頭部:在請求跟響應裡都有,跟訊息體裡傳輸的資料沒有關係。

  • 請求頭部:更多的是關於被請求資源或者客戶端的資訊。

  • 響應頭部:響應的額外資訊。

  • 實體頭部:訊息體的額外資訊,比如content-length或MIMI-type。

資源

資源可以是由系統暴露出來的任何具有唯一標識的東西。資源在應用領域跟客戶端之間建立起了聯絡。一張圖片,一個表格,或者它們的集合,都被看作資源。資源通過某種呈現方式被獲取或被建立(XML,JSON等)。

我們與之打交道的是資源的呈現形式,並不是資源本身,這個跟值傳遞有點像。根據之前對REST的定義,資源代表了在網路上傳輸的文件。伺服器端關心資源的狀態,因為它們代表了領域的狀態。而客戶端只是獲取或者傳送資源的呈現狀態,從而讓應用的狀態發生變化。客戶端關心的是應用的狀態,因為這些狀態的變化跟應用所要達成的目標有關。

資源的名字都應該是具有名詞性質的,它們代表的是系統中領域的概念,並用URI標識。

URIs (Uniform Resource Identifiers)

URIs用來唯一標識資源。要訪問或者操作一個資源,最起碼要知道資源的地址。它們由協議+伺服器地址+路徑組成。

客戶端不應該與資源的URI有太多耦合,因為服務端可能隨意改變它們的值。在這一點上,超媒體更具優勢。它提供了一種解耦客戶端跟URI的方式,並在應用協議中加入新的語義。

超媒體

超媒體通過超媒體控制元件(比如連結跟表單)或者URI告訴客戶端接下來可以做什麼。針對特定應用的超媒體格式是在應用的Media Type裡定義的。

超連結由href屬性和rel屬性組成,href指定要訪問資源的URI,rel定義了資源跟URI的關係。超媒體通過它們嚮應用的狀態轉移增加新的語義。服務端通過在響應中增加新的超連結來擴充套件新的功能,而不會對客戶端造成影響。只要服務端在響應裡一直保留之前的連結,客戶端可以像之前那樣工作,只是在要訪問新資源的時候才需要更新。超媒體的另一個優勢是它引入了可發現性,它提供了一種可以暴露資源的方式,而且它是一種自文件的協議。

客戶端通過一個固定的URL跟app開始了互動,服務端在每一個響應裡提供了後續操作的超連結,這些連結具有良好的媒體格式,客戶端沿著這些連結可以做相應的操作。

超媒體跟連結定義了伺服器跟客戶端之間的契約。客戶端通過連結與系統進行互動,這就是HATEOAS(超媒體作為應用狀態的引擎)所表達的意思。

Richardson成熟度模型

這個模型幫助我更好地理解REST,以及如何去解釋web應用的屬性。它把REST系統的元件分為三個等級,並提供了一種方式去理解RESTful相關的想法,概念和優勢。它更像是一種理論教育模型,而不是一種評審機制。

關於Richardson成熟度模型更具體的解釋可以看這裡

原文地址:https://dzone.com/articles/what-does-restful-really-mean

相關文章