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)用在多工作業系統中,使得同時執行的任務能互相會話。這些任務共享記憶體空間使任務同步和互相傳送資訊。