REST(一種軟件架構風格)
全稱:Representational State Transfer
含義:(表述性 狀態 轉移)
是一種針對網絡應用的設計和開發方式,可以降低開發的復雜性,提高系統的可伸縮性。
在目前主流的三種Web服務交互方案中,REST相比於SOAP(Simple Object Access protocol,簡單對象訪問協議)以及XML-RPC更加簡單明了,無論是對URL的處理還是對Payload的編碼,REST都傾向於用更加簡單、輕量的方法設計和實現。值得注意的是REST並沒有一個明確的標准,而更像是一種設計的風格。
原則條件
REST 指的是一組架構約束條件和原則,如果你在設計應用程序時能堅持REST原則,那就預示着你將會得到一個使用了優質Web架構的系統。Web 應用程序最重要的 REST 原則是:
- 客戶端和服務器之間的交互在請求之間是無狀態的。
- 從客戶端到服務器的每個請求都必須包含理解請求所必需的信息。
- 如果服務器在請求之間的任何時間點重啟,客戶端不會得到通知。
- 無狀態請求可以由任何可用服務器回答,這十分適合雲計算之類的環境。
- 客戶端可以緩存數據以改進性能。
- 在服務器端,應用程序狀態和功能可以分為各種資源。資源是一個概念實體,它向客戶端公開。資源的例子有:應用程序對象、數據庫記錄、算法等等。每個資源都使用 URI (Universal Resource Identifier) 得到一個唯一的地址。所有資源都共享統一的接口,以便在客戶端和服務器之間傳輸狀態。
- 使用的是標准的 HTTP 方法,比如 GET、PUT、POST 和 DELETE。Hypermedia 是應用程序狀態的引擎,資源表示通過超鏈接互聯。
注意:
REST除了給我們帶來了一個嶄新的架構以外,還有一個重要的貢獻是在開發系統過程中的一種新的思維方式:通過url來設計系統的結構。根據REST,每個url都代表一個resource,而整個系統就是由這些resource組成的。因此,如果url是設計良好的,那么系統的結構就也應該是設計良好的。
RESTful:(REST式的)
基於REST這種軟件架構風格設計的 API接口 即稱為:RESTful API
即設計的這些接口滿足 RESTful 接口設計規范
接口設計規范的具體內容為:
1. 域名
應該盡量將API部署在專用域名之下。
https://api.example.com
如果確定API很簡單,不會有進一步擴展,可以考慮放在主域名下。
https://example.org/api/
2. 版本(Versioning)
應該將API的版本號放入URL。
http://www.example.com/app/1.0/foo
http://www.example.com/app/1.1/foo
http://www.example.com/app/2.0/foo
另一種做法是,將版本號放在HTTP頭信息中,但不如放入URL方便和直觀。Github就采用了這種做法。
因為不同的版本,可以理解成同一種資源的不同表現形式,所以應該采用同一個URL。版本號可以在HTTP請求頭信息的Accept字段中進行區分(參見Versioning REST Services):
Accept: vnd.example-com.foo+json; version=1.0
Accept: vnd.example-com.foo+json; version=1.1
Accept: vnd.example-com.foo+json; version=2.0
3. 路徑(Endpoint)
路徑又稱"終點"(endpoint),表示API的具體網址,每個網址代表一種資源(resource)
(1) 資源作為網址,只能有名詞,不能有動詞,而且所用的名詞往往與數據庫的表名對應。
舉例來說,以下是不好的例子:
/getProducts
/listOrders
/retreiveClientByOrder?orderId=1
對於一個簡潔結構,你應該始終用名詞。 此外,利用的HTTP方法可以分離網址中的資源名稱的操作。
GET /products :將返回所有產品清單
POST /products :將產品新建到集合
GET /products/4 :將獲取產品 4
PATCH(或)PUT /products/4 :將更新產品 4
(2) API中的名詞應該使用復數。無論子資源或者所有資源。
舉例來說,獲取產品的API可以這樣定義
獲取單個產品:http://127.0.0.1:8080/AppName/rest/products/1
獲取所有產品: http://127.0.0.1:8080/AppName/rest/products
4. HTTP動詞
對於資源的具體操作類型,由HTTP動詞表示。
常用的HTTP動詞有下面四個(括號里是對應的SQL命令)。
- GET(SELECT):從服務器取出資源(一項或多項)。
- POST(CREATE):在服務器新建一個資源。
- PUT(UPDATE):在服務器更新資源(客戶端提供改變后的完整資源)。
- DELETE(DELETE):從服務器刪除資源。
還有三個不常用的HTTP動詞。
- PATCH(UPDATE):在服務器更新(更新)資源(客戶端提供改變的屬性)。
- HEAD:獲取資源的元數據。
- OPTIONS:獲取信息,關於資源的哪些屬性是客戶端可以改變的。
下面是一些例子。
GET /zoos:列出所有動物園
POST /zoos:新建一個動物園(上傳文件)
GET /zoos/ID:獲取某個指定動物園的信息
PUT /zoos/ID:更新某個指定動物園的信息(提供該動物園的全部信息)
PATCH /zoos/ID:更新某個指定動物園的信息(提供該動物園的部分信息)
DELETE /zoos/ID:刪除某個動物園
GET /zoos/ID/animals:列出某個指定動物園的所有動物
DELETE /zoos/ID/animals/ID:刪除某個指定動物園的指定動物
5. 過濾信息(Filtering)
如果記錄數量很多,服務器不可能都將它們返回給用戶。API應該提供參數,過濾返回結果。
下面是一些常見的參數。query_string 查詢字符串,地址欄后面問號后面的數據,格式: name=xx&sss=xxx
?limit=10:指定返回記錄的數量
?offset=10:指定返回記錄的開始位置。
?page=2&per_page=100:指定第幾頁,以及每頁的記錄數。
?sortby=name&order=asc:指定返回結果按照哪個屬性排序,以及排序順序。
?animal_type_id=1:指定篩選條件
參數的設計允許存在冗余,即允許API路徑和URL參數偶爾有重復。比如,GET /zoos/ID/animals 與 GET /animals?zoo_id=ID 的含義是相同的。
6. 狀態碼(Status Codes)
服務器向用戶返回的狀態碼和提示信息,常見的有以下一些(方括號中是該狀態碼對應的HTTP動詞)。
- 200 OK - [GET]:服務器成功返回用戶請求的數據
- 201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數據成功。
- 202 Accepted - [*]:表示一個請求已經進入后台排隊(異步任務)
- 204 NO CONTENT - [DELETE]:用戶刪除數據成功。
- 400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發出的請求有錯誤,服務器沒有進行新建或修改數據的操作
- 401 Unauthorized - [*]:表示用戶沒有權限(令牌、用戶名、密碼錯誤)。
- 403 Forbidden - [*] 表示用戶得到授權(與401錯誤相對),但是訪問是被禁止的。
- 404 NOT FOUND - [*]:用戶發出的請求針對的是不存在的記錄,服務器沒有進行操作,該操作是冪等的。
- 406 Not Acceptable - [GET]:用戶請求的格式不可得(比如用戶請求JSON格式,但是只有XML格式)。
- 410 Gone -[GET]:用戶請求的資源被永久刪除,且不會再得到的。
- 422 Unprocesable entity - [POST/PUT/PATCH] 當創建一個對象時,發生一個驗證錯誤。
- 500 INTERNAL SERVER ERROR - [*]:服務器發生錯誤,用戶將無法判斷發出的請求是否成功。
7. 錯誤處理(Error handling)
如果狀態碼是4xx,服務器就應該向用戶返回出錯信息。一般來說,返回的信息中將error作為鍵名,出錯信息作為鍵值即可。
{
error: "Invalid API key"
}
8. 返回結果
針對不同操作,服務器向用戶返回的結果應該符合以下規范。
- GET /collection:返回資源對象的列表(數組)
- GET /collection/ID:返回單個資源對象(json)
- POST /collection:返回新生成的資源對象(json)
- PUT /collection/ID:返回完整的資源對象(json)
- DELETE /collection/ID:返回一個空文檔(空字符串)
9. 超媒體(Hypermedia API)
RESTful API最好做到Hypermedia(即返回結果中提供鏈接,連向其他API方法),使得用戶不查文檔,也知道下一步應該做什么。
比如,Github的API就是這種設計,訪問api.github.com會得到一個所有可用API的網址列表。
{
"current_user_url": "https://api.github.com/user",
"authorizations_url": "https://api.github.com/authorizations",
// ...
}
從上面可以看到,如果想獲取當前用戶的信息,應該去訪問api.github.com/user,然后就得到了下面結果。
{
"message": "Requires authentication",
"documentation_url": "https://developer.github.com/v3"
}
上面代碼表示,服務器給出了提示信息,以及文檔的網址。
10. 其他
服務器返回的數據格式,應該盡量使用JSON,避免使用XML。
RESTful架構
RESTful架構是對MVC架構改進后所形成的一種架構,通過使用事先定義好的接口與不同的服務聯系起來。在RESTful架構中,瀏覽器使用POST,DELETE,PUT和GET四種請求方式分別對指定的URL資源進行增刪改查操作。因此,RESTful是通過URI實現對資源的管理及訪問,具有擴展性強、結構清晰的特點。
RESTful架構將服務器分成前端服務器和后端服務器兩部分,前端服務器為用戶提供無模型的視圖;后端服務器為前端服務器提供接口。瀏覽器向前端服務器請求視圖,通過視圖中包含的AJAX函數發起接口請求獲取模型。
項目開發引入RESTful架構,利於團隊並行開發。在RESTful架構中,將多數HTTP請求轉移到前端服務器上,降低服務器的負荷,使視圖獲取后端模型失敗也能呈現。但RESTful架構卻不適用於所有的項目,當項目比較小時無需使用RESTful架構,項目變得更加復雜。
RESTful與 RPC
使用 RPC 樣式架構構建的基於 SOAP 的 Web 服務成為實現 SOA 最常用的方法。RPC 樣式的 Web 服務客戶端將一個裝滿數據的信封(包括方法和參數信息)通過 HTTP 發送到服務器。服務器打開信封並使用傳入參數執行指定的方法。方法的結果打包到一個信封並作為響應發回客戶端。客戶端收到響應並打開信封。每個對象都有自己獨特的方法以及僅公開一個 URI 的 RPC 樣式 Web 服務,URI 表示單個端點。它忽略 HTTP 的大部分特性且僅支持 POST 方法。
由於輕量級以及通過 HTTP 直接傳輸數據的特性,Web 服務的 RESTful 方法已經成為最常見的替代方法。可以使用各種語言(比如 Java 程序、Perl、Ruby、Python、PHP 和 Javascript[包括 Ajax])實現客戶端。RESTful Web 服務通常可以通過自動客戶端或代表用戶的應用程序訪問。但是,這種服務的簡便性讓用戶能夠與之直接交互,使用它們的 Web 瀏覽器構建一個 GET URL 並讀取返回的內容。
在 REST 樣式的 Web 服務中,每個資源都有一個地址。資源本身都是方法調用的目標,方法列表對所有資源都是一樣的。這些方法都是標准方法,包括 HTTP GET、POST、PUT、DELETE,還可能包括 HEAD 和 OPTIONS。
在 RPC 樣式的架構中,關注點在於方法,而在 REST 樣式的架構中,關注點在於資源 —— 將使用標准方法檢索並操作信息片段(使用表示的形式)。資源表示形式在表示形式中使用超鏈接互聯。
Leonard Richardson 和 Sam Ruby 在他們的著作 RESTful Web Services 中引入了術語 REST-RPC 混合架構。REST-RPC 混合 Web 服務不使用信封包裝方法、參數和數據,而是直接通過 HTTP 傳輸數據,這與 REST 樣式的 Web 服務是類似的。但是它不使用標准的 HTTP 方法操作資源。它在 HTTP 請求的 URI 部分存儲方法信息。好幾個知名的 Web 服務,比如 Yahoo 的 Flickr API 和 Delicious API 都使用這種混合架構。
RPC
RPC是遠程過程調用(Remote Procedure Call)的縮寫形式。
SAP系統RPC調用的原理其實很簡單,有一些類似於三層構架的C/S系統,第三方的客戶程序通過接口調用SAP內部的標准或自定義函數,獲得函數返回的數據進行處理后顯示或打印。
原理圖示:
應用場景:
RPC在分布式系統中的系統環境建設和應用程序設計中有着廣泛的應用,應用包括如下方面:
1、分布式操作系統的進程間通訊
進程間通訊是操作系統必須提供的基本設施之一,分布式操作系統必須提供分布於異構的結點機上進程間的通訊機制,RPC是實現消息傳送模式的分布式進程間通訊的手段之一。
2、構造分布式計算的軟件環境
由於分布式軟件環境本身地理上的分布性, 它的各個組成成份之間存在大量的交互和通訊,R P C 是其基本的實現方法之一。ONC+和DCE兩個流行的分式布計算軟件環境都是使用RPC構造的,其它一些分布式軟件環境也采用了RPC方式。
3、遠程數據庫服務
在分布式數據庫系統中,數據庫一般駐存在服務器上,客戶機通過遠程數據庫服務功能訪問數據庫服務器,現有的遠程數據庫服務是使用RPC模式的。例如,Sybase和Oracle都提供了存儲過程機制,系統與用戶定義的存儲過程存儲在數據庫服務器上,用戶在客戶端使用RPC模式調用存儲過程。
4、分布式應用程序設計
RPC機制與RPC工具為分布式應用程序設計提供了手段和方便, 用戶可以無需知道網絡結構和協議細節而直接使用RPC工具設計分布式應用程序。
5、分布式程序的調試
RPC可用於分布式程序的調試。使用反向RPC使服務器成為客戶並向它的客戶進程發出RPC,可以調試分布式程序。例如,在服務器上運行一個遠端調試程序,它不斷接收客戶端的RPC,當遇到一個調試程序斷點時,它向客戶機發回一個RPC,通知斷點已經到達,這也是RPC用於進程通訊的例子。
IPC:進程間通信
進程間通信(IPC)是在多任務操作系統或聯網的計算機之間運行的程序和進程所用的通信技術。有兩種類型的進程間通信(IPC)。
LPC:本地過程調用
本地過程調用(LPC)用在多任務操作系統中,使得同時運行的任務能互相會話。這些任務共享內存空間使任務同步和互相發送信息。