RESTFul應用分析

Restful API 近年來應用愈來愈普遍,各大互聯網公司紛紛推出了本身的 Restful API 服務。html

本文將從實際應用出發,從 REST 到 Restful 再到 Restful API ,逐一進行介紹和分析。sql


REST 風格

REST 風格最先由 Roy Thomas Fielding 博士提出, REST 是一種系統架構設計風格,主要面向基於網絡的軟件架構設計。這一架構風格,包含了如下一些基本要求:json

客戶-服務器

在 REST 風格中,最基本的要求就是對於一個程序來講,應當分離用戶接口和數據存儲,改善用戶接口跨平臺遷移的可移植性,同時簡化服務器組件,改善系統的可伸縮性。瀏覽器

對於這一點,目前咱們所接觸到的大多數應用都已經使用了這一模式,不管是瀏覽器,仍是自主開發的客戶端程序,其根本的實現方式都是採用了 客戶-服務器 模式。客戶端負責與用戶之間的交互處理,而服務器端則實現數據存儲以及相關的業務邏輯。緩存

同時,對於服務器端,完整的系統大部分狀況下都會包含多個不一樣的模塊,這些模塊之間的調用也應當遵循 客戶-服務器 的模式,模塊之間經過接口進行互相訪問。安全

無狀態

服務端在設計接口時,應當設計爲無狀態接口。也就是說,服務器端不保存任何與客戶端相關的狀態上下文信息,客戶端在每次調用服務端接口時,須要提供足夠的信息,以供服務端完成操做。ruby

在無狀態的設計中,服務端減小了保存客戶端相關上下文數據,所以,一方面服務端可以更加容易的實現動態擴展,而不至於影響客戶端使用;另外一方面則減小了服務端從故障中恢復的任務量。服務器

但無狀態也會帶來額外的問題。客戶端將須要保存完整的用戶狀態信息,在每次與服務端交互時可能須要增長與用戶狀態相關的上下文信息,這樣將致使請求數據的重複和增大。網絡

緩存

根據接口的實際狀況,應當在接口設計中增長緩存策略,服務端能夠決定是否能夠緩存當前返回的數據。經過此種方式,能夠在必定程度上減小實際到達服務端請求,從而提升網絡訪問性能。架構

但緩存須要謹慎使用,緩存哪些數據,緩存過時時間都是須要根據實際狀況進行設計。適當的緩存能夠有效的提升系統效率,可是若是設計不當,將有可能致使大量的過時數據,進而影響系統運行。

通常而言,數據字典類數據、修改頻率很是低的數據、實時性要求很低的數據等,這些數據能夠設計必定的緩存策略,以提升系統運行效率。

系統分層

在設計系統,尤爲是大型系統,一般須要將系統按照不一樣的功能進行橫向和縱向的分層。例如橫向分層通常可分爲交互層、服務層、數據層等,而縱向分層則一般會按照不一樣的業務功能對系統進行切分。通過分層後,系統將劃分爲不一樣的模塊進行獨立開發部署運行。系統分層後,不一樣的模塊能夠獨立進化,實現功能解耦,提升整個系統的可擴展性。

統一接口

統一接口,便是不一樣系統模塊之間的調用接口統一規範,使用統一的調用協議,統一的數據格式等。統一接口帶來的是系統交互的規範化,接口調用與業務解耦,各模塊獨立進化。

以上便是對於 REST 風格的解釋說明。REST 自己是一種系統架構設計風格,所以其更加偏向理論性。如下的內容將專一於實際場景中運用 REST 風格。


Restful 實現

REST 風格是面向網絡的軟件架構設計風格,其針對的是基於網絡的軟件架構。當軟件架構設計符合 REST 風格時,則能夠描述爲該設計是 Restful 的。而在實際場景中,REST 論文中描述了應用 REST 風格基本方式,即 REST (表述性狀態轉移)。

面向資源

網絡上的一個實體,一個具體信息,均可以描述爲一個 資源 ,資源能夠是文本、圖片、音頻、服務等具體存在。在網絡中,每種資源都對應與一個 URI (統一資源標識符)地址,經過 URI 就能夠訪問到該資源。而咱們一般的上網,便是對資源的各類操做。

在 Restful 架構中,全部的接口應當採用面向資源的接口設計,即對於接口的訪問地址指向其 URI 地址。

表述性

資源在網絡上呈現出來的多是多種形式,例如 HTML 、 XML 、 JSON 、圖片等等。而客戶端與服務器之間則傳輸的是資源的這種具體表現形式。客戶端與服務端的互動,本質上就是經過這些表現形式,實現對資源的操做。

按照面向資源接口設計的要求,一般所見到的 URI 地址中,*.html / *.xml / *.json 等擴展名,其實都指向了當前資源的具體表現形式,而 URI 嚴格意義上僅指向了資源實體,並不包含具體表現形式。

狀態轉移

爲了使操做資源,也即便資源發生狀態轉移,按照 REST 的要求,客戶端若想要操做服務端資源,須要經過 HTTP 協議進行操做。而在 HTTP 協議中,規定了若干用於具體操做的動詞,指向了不一樣的操做類型。

通常而言,對於資源的操做能夠表示 CRUD 四類最基本的操做,即 增刪改查 。而 HTTP 協議中的一般用如下動詞表示這四類具體的操做:

  • GET :查詢資源操做。

  • POST :新建資源操做,也能夠用於更新資源。

  • PUT :更新資源操做。

  • DELETE :刪除資源操做。

在實際應用中,客戶端與服務端之間的交互,便是創建在 HTTP 協議之上,經過面向資源的接口地址,使用 HTTP 協議動詞做爲操做描述,進而實現客戶端與服務端的交互過程。


Restful API 設計

在 REST 提出多年來,當前對於 REST 風格的應用最多的便是 Restful API 。

Restful API 通常分爲對外和對內。對外的 Restful API 爲面向公網的公共服務接口,此類接口通常能夠經過公網直接訪問,或是通過必定的安全認證後經過公網訪問。而對內的 Restful API 則主要是一整套系統內部各個子系統或模塊之間交互的標準接口,相對於對外的 Restful API 接口,內部 API 接口更加標準化。

按照 REST 的要求,Restful API 的設計能夠總結出如下的一些具體要求。

HTTPS + 域名

Restful API 的無狀態性,要求客戶端須要在調用接口時傳入足夠的信息以供服務端用於操做指定的資源,這就有可能使得接口數據在網絡傳輸過程當中遭到攔截致使更多的數據泄漏。所以在提供 Restful API ,特別是對外的 API 時,應當儘量的使用 HTTPS 協議,以確保傳輸過程的安全。

另外一方面,在 API 地址中使用域名,能夠進一步解耦服務端與客戶端,服務端能夠更加容易的遷移和擴展,而不會影響服務端的使用。

例如:

https://open.domain.com/

實際應用過程當中,使用 HTTPS 協議,更多應用與對外的 Restful API 接口,而對內網的 Restful API 來講,能夠在信任內網安全的前提下,使用 HTTP 協議,以下降複雜度,提升效率。

URL 指向資源,HTTP 動詞指向操做

按照 REST 的要求,Restful API 的 URL 地址應指向具體的一個資源,例如用戶 user 。URL 中應當只包含資源名詞,不該該包含指向操做的動詞,例如新建、查詢、修改、刪除等。具體操做經過 HTTP 動詞( GET / POST / PUT / DELETE )指定。

例如,傳統的訪問地址,獲取用戶信息:

https://open.domain.com/app/getUser

此時的 URL 地址指向了 獲取用戶 這一具體的操做過程,這也就是傳統的 RPC 形式。而按照 Restful API 的設計,該實例將設計爲以下形式:

https://open.domain.com/app/user

// HTTP GET 請求

此時的 URL 地址指向了 user 這一資源實體,而經過 HTTP 協議中的 GET 動詞指定了該請求爲 獲取用戶 請求。

指定 API 版本號

在設計 Restful API 時,特別是對外的 API ,一般須要考慮 API 多版本的問題,由於 API 會進行升級,而客戶端則處於不可控狀態,可能沒法及時對 API 調用過程進行配合升級。所以,服務端須要提供對不一樣版本 API 的支持,同時,客戶端在調用 API 時也須要指定特定的版本號,以確保調用過程正常進行。

版本號的指定,能夠在 URL 中,也能夠在 HTTP 頭信息中。

例如,在 URL 中指定版本號:

https://open.domain.com/v1/app/user

這種指定版本號的方式相對簡單直觀,但將致使指向統一資源的 URL 產生多個,增長了管理 URL 的成本和複雜度。

例如,在 HTTP 頭信息中增長版本號:

https://open.domain.com/app/user

HTTP 頭:
API-Vsersion: 1

以上實例中,在 HTTP 請求的頭信息中增長了自定義字段,用於表示 Restful API 版本。這種方式不會產生多個 URL ,但其問題是不夠直觀和簡潔,客戶端和服務端增長了區分版本號的難度,在在一些特定狀況下,例如瀏覽器端的 HTTP 請求,難以對 HTTP 請求的頭信息進行更改。

指定參數

在 Restful API 請求中,可能須要根據不一樣的狀況進行過濾,須要增長操做參數。通常來講,針對 GET 和 DELTE 請求須要增長操做參數的狀況較多,而 POST 和 PUT 更多的是經過 HTTP 報文體提供操做數據信息。

指定參數能夠經過兩種方式:URL 地址參數,? 參數。

URL 地址參數:即在 URL 以後,繼續按照 URL 格式拼接參數,服務端接到請求後,經過識別 URL 中字符串的位置,獲取不一樣的參數。

例如:

https://open.domain.com/app/user/123456/Adminhttps://open.domain.com/app/user/123456/Admin

在以上實例中, 123456 表明用戶 ID 參數值, Admin 則表明用戶類型參數值,後臺解析該 URL 後便可根據字符串位置獲取到特定的參數。

? 參數:即經過 QueryString 查詢字符串的形式,拼接到 URL 以後,查詢字符串的格式以下:

?key1=value1&key2=value2&...

例如:

https://open.domain.com/app/user?id=123456&type=Admin

以上實例中,服務端經過解析 ? 以後的字符串獲取特定的參數。

使用 JSON 做爲返回數據格式

相對於 XML 格式來講,JSON 格式更加簡潔易用,佔用數據量更小,在以網絡爲基礎,使用 HTTP 協議的 Restful API 中,使用 JSON 做爲返回數據格式更加合理。

例如:

// JSON 格式
{"name":"user","type":"Admin"}

// XML 格式
<user><name>user</name><type>Admin</type></user>

使用安全認證機制

在使用 Restful API ,特別是對公網開放的 Restful API,一般須要經過必定的安全認證機制來進行實現訪問控制。目前主流的方案是經過 OAuth2.0 實現安全認證。


Restful API 分析

Restful API 的興起,證實了其具有相比於傳統 RPC 接口的優點。當一樣的,Restful API 在實際應用過程當中,也存在這本身的劣勢和問題。

Restful API 優點

Restful API 充分利用了 HTTP 協議的設計,使用面向資源的接口設計,相對於傳統 RPC 下降了接口設計的複雜度。

例如,使用傳統 RPC 形式設計針對用戶對象的 CRUD 操做:

// 新建用戶
https://open.domain.com/app/addUser
// 查詢用戶
https://open.domain.com/app/retrieveUser
// 更新用戶
https://open.domain.com/app/updateUser
// 刪除用戶
https://open.domain.com/app/deleteUser

在以上實例中,須要經過四個 URL 來實現 CRUD 操做。而經過 Restful API 設計,可爲以下實例:

// GET: 查詢用戶;POST: 新建用戶;PUT: 更新用戶;DELETE: 刪除用戶 https://open.domain.com/app/user// GET: 查詢用戶;POST: 新建用戶;PUT: 更新用戶;DELETE: 刪除用戶 https://open.domain.com/app/user

在以上實例中,經過 HTTP 動詞指定了不一樣的 CRUD 操做,將接口 URL 簡化爲了同一個地址,僅須要改變 HTTP 動詞便可實現不一樣的操做。

另外一方面,相對於 SOAP/XML 形式的 RPC 服務,Restful API 採用 HTTP/JSON 的形式傳遞數據,下降了傳輸數據量,同時提升了數據解析的效率,單位時間內的負載能力會高於 SOAP WebService 服務。

例如,對於 SOAP WebService 來講,基本的請求響應格式以下:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header>
    </soapenv:Header>
    <soapenv:Body>
    </soapenv:Body>
</soapenv:Envelope>

而對於 Restful API 來講,其請求格式符合 HTTP 協議的要求,返回格式則符合標準的 JSON 格式便可。

Restful API 劣勢

Restful API 面向資源設計接口,而對於一些複雜操做來講,接口設計難度將遠大於 RPC 形式。

例如,用戶登陸驗證,使用 RPC 形式設計接口以下:

https://open.domain.com/app/checkUser

在以上實例中,對於 Restful API 而言,很難將該業務歸類爲 HTTP 動詞中的某一種。又好比「下單」這一功能,它涉及到了訂單、用戶、支付帳戶等多個資源實體的多種操做,所以一樣也難以設計爲 Restful API 。

Restful API 具有高效簡潔的特色,但這也所以形成 Restful API 沒有相似於 SOAP 協議的規範性協議,Restful API 中的數據格式、標準、安全性等都須要由開發者決定,這也就形成了沒法創建統一的 Restful API 標準,做爲客戶端可能須要適配多種格式的 Restful API 。

Restful API 可能遇到的問題

當 Restful API 存在多版本時,服務端須要維護多版本的接口,這會致使更多的維護成本,並且隨着 API 的不斷升級,多版本的成本將會愈來愈高,如何通知客戶端進行接口版本升級一樣也是可能遇到的問題。

當使用 URL 地址參數形式時,對於可選參數,服務端難以實現正確的讀取。在 API 存在可選參數的狀況下,URL 地址中的參數位置是不固定的,所以服務端很難判斷參數所處的正確位置。

針對特定的業務功能,難以徹底按照 Restful 要求進行設計。例如用戶驗證、訂單提交等涉及到多個資源實體和多種操做的業務流程,其一個接口中須要完成多項相關聯的操做,若使用 RPC 形式設計接口,則設計爲一個統一的接口便可,而使用 Restful API 則可能出現多個接口且接口間存在調用依賴,這將會增長客戶端和服務端的處理難度。

Restful 自己並無安全性方面的標準,須要根據不一樣的使用場景設計 API 的安全控制方案。目前經常使用的安全方案便是經過 OAuth2.0 進行安全認證,但不一樣的 API 在安全認證機制方面也會存在必定的差異,若是設計統一完善的安全機制,也是須要考慮的問題。


Restful API 使用場景

根據 Restful API 的特定,其應用場景能夠參考如下的場景:

  • 資源集中型服務,例如針對用戶的信息查詢,針對訂單的信息查詢的等,這類型服務以資源實體爲中心,操做大多爲簡單的 CRUD 操做,業務邏輯簡單。

  • 訪問量大,且對訪問時效要求比較高的服務。Restful API 相對於 SOAP WebService 來講,數據量更小,解析更快,在網絡環境下可以提升訪問的速度和承載能力。

  • 面向公網的,且安全性要求較低的開放型 API 服務。這類服務一般由開發者向公網的全部使用者開放,Restful API 的形式可以簡化服務調用過程,提升訪問效率。

對於複雜業務操做,例如保全申請提交,理賠申請提交等,使用 Restful API 形式難以進行設計,所以此類的業務可使用傳統 RPC 的接口形式進行設計,SOAP WebService 或者 HTTP/JSON 形式的 RPC 都是可行的選擇,使用 RPC 形式反而會更加簡單。

選擇哪一種方式的接口設計,須要根據實際的應用狀況進行調整,沒有最好的,只有最合適的。


傳統 RPC 服務改造

在已經成型的系統當中,多數調用採用了 RPC 形式進行設計,並使用 SOAP WebService 做爲具體的實現方式,並且開發者也已經習慣了使用了 RPC 的形式設計服務接口。在這種狀況下,若想要向 Restful API 形式改造,將付出大量的改形成本。已有系統中存在錯綜複雜的調用邏輯,而接口也多數都是面向過程的,這種狀況下改造接口,須要在接口設計上進行大幅改動纔可以實現 Restful API。同時,開發者也須要在設計開發接口時轉變思想,以面向資源的方式進行接口設計,這也是須要面臨的問題。

而對於新建系統來講,不存在歷史接口,則能夠從頭按照 REST 風格進行設計,接口可設計爲 Restful API,其成本要小於對已有系統的改造。

相關文章
相關標籤/搜索