摘要
軟件開發(fā)從單機軟件到互聯(lián)網(wǎng)化,從互聯(lián)網(wǎng)單體應(yīng)用到系統(tǒng)拆分、前后端分離舔腾,再到現(xiàn)在的微服務(wù)叛溢。軟件架構(gòu)越來越龐大復(fù)雜,相關(guān)聯(lián)的領(lǐng)域劃分更細(xì)致、職責(zé)更專一,這樣各部分之間的交互就很頻繁。RESTful作為一種架構(gòu)風(fēng)格颈畸、一種接口設(shè)計規(guī)范,簡單没讲、標(biāo)準(zhǔn)眯娱、易擴展讓其得到了越來越多的應(yīng)用。然而在實際工作中爬凑,REST API也會帶來一些新的挑戰(zhàn):接口無法抽象為資源徙缴、多變的URI不容易做監(jiān)控等。
什么是REST API嘁信?
REST 全稱 Representational State Transfer于样,翻譯為資源表現(xiàn)層狀態(tài)轉(zhuǎn)化,資源指服務(wù)中的實體或信息潘靖;表現(xiàn)層指信息的展現(xiàn)形式穿剖,如json、xml卦溢、html等糊余;狀態(tài)轉(zhuǎn)化指接口訪問過程中數(shù)據(jù)和狀態(tài)的變化,作為http無狀態(tài)服務(wù)单寂,業(yè)務(wù)的實現(xiàn)必然要涉及到數(shù)據(jù)和狀態(tài)的變化贬芥。
RESTful的本質(zhì)是一種軟件架構(gòu)風(fēng)格,核心在于面向資源設(shè)計接口宣决,即將所有的接口描述為對資源的操作蘸劈,目的在于降低開發(fā)的復(fù)雜性,提高系統(tǒng)的可伸縮性尊沸。設(shè)計的準(zhǔn)則主要有以下幾點:
- REST API 圍繞資源設(shè)計威沫,資源是可由客戶端訪問的任何類型的對象贤惯、數(shù)據(jù)或服務(wù)。每個資源有一個標(biāo)識符壹甥,即唯一標(biāo)識該資源的 URI救巷。
- 客戶端通過交換資源的表示形式來與服務(wù)交互壶熏。REST API 使用統(tǒng)一接口句柠,這有助于分離客戶端和服務(wù)實現(xiàn)。 對于基于 HTTP 構(gòu)建的 REST API棒假,統(tǒng)一接口包括使用標(biāo)準(zhǔn) HTTP 謂詞對資源執(zhí)行操作溯职。 最常見的操作是 GET、POST帽哑、PUT谜酒、PATCH 和 DELETE。
- REST API 使用無狀態(tài)請求模型妻枕。
URI標(biāo)識資源
REST API采用面向資源的思想僻族,所以在設(shè)計之初首先需要考慮的是有哪些資源可供操作。資源是一個很寬泛的概念屡谐,任何寄宿于Web可供操作的事物均可視為資源述么。資源可以體現(xiàn)為經(jīng)過持久化處理保存到磁盤上的某個文件或者數(shù)據(jù)庫中某個表的某條記錄,也可以是Web應(yīng)用接受到請求后采用某種算法計算得出的結(jié)果愕掏。資源可以體現(xiàn)為一個具體的物理對象度秘,它也可以是一個抽象的流程。
一個資源必須具有一個或者多個標(biāo)識饵撑,既然我們設(shè)計的Web API剑梳,那么很自然地應(yīng)該采用URI來作為資源的標(biāo)識。作為資源標(biāo)識的URI最好具有可讀性滑潘,因為具有可讀性的URI更容易被使用垢乙,使用者一看就知道被標(biāo)識的是何種資源,比如如下一些URI就具有很好的可讀性语卤。
http://www.artech.com/employees/c001(編號C001的員工)
http://www.artech.com/sales/2013/12/31(2013年12月31日的銷售額)
http://www.artech.com/orders/2013/q4(2013年第4季度簽訂的訂單)
除了必要的標(biāo)志性和可選的可讀性之外侨赡,標(biāo)識資源的URI應(yīng)該具有可尋址性。也就是說粱侣,URI不僅僅指明了被標(biāo)識資源所在的位置羊壹,而且通過這個URI可以直接獲取目標(biāo)資源,即每個資源有一個唯一標(biāo)識該資源的 URI齐婴。
HTTP方法表示動作
對于Web來說油猫,針對資源的操作通過HTTP方法來體現(xiàn)。常見的HTTP方法有其中:GET柠偶、HEAD情妖、DELETE睬关、PUT、POST毡证、PATCH电爹。它們的含義如下:
- GET 檢索位于指定 URI 處的資源的表示形式。 響應(yīng)消息的正文包含所請求資源的詳細(xì)信息料睛。
- HEAD 獲取目標(biāo)資源的元數(shù)據(jù)信息丐箩,服務(wù)器一般將對應(yīng)資源的元數(shù)據(jù)置于響應(yīng)的報頭集合返回給客戶端,這樣的響應(yīng)一般正文恤煞。
- POST 在指定的 URI 處創(chuàng)建新資源屎勘。 請求消息的正文將提供新資源的詳細(xì)信息。
- PUT 在指定的 URI 處創(chuàng)建或替換資源居扒。 請求消息的正文指定要創(chuàng)建或更新的資源概漱。
- PATCH 對資源執(zhí)行部分更新。 請求正文包含要應(yīng)用到資源的一組更改喜喂。
- DELETE 刪除位于指定 URI 處的資源瓤摧。
需要注意的是:對于發(fā)送PUT請求以修改某個存在的資源,服務(wù)器一般會將提供資源將原有資源整體覆蓋掉玉吁;如果需要進行局部修改照弥,推薦采用PATCH方法,因為從語義上講Patch就是打補丁的意思诈茧。PUT 請求必須是冪等的产喉。 如果客戶端多次提交同一個 PUT 請求,結(jié)果應(yīng)始終相同敢会,而我們不需要保證保證 POST 和 PATCH 請求的冪等性曾沈。
無狀態(tài)性
REST只維護資源的狀態(tài),而不需要維護客戶端的狀態(tài)鸥昏。對于它來說塞俱,每次請求都是全新的,它只需要針對本次請求作相應(yīng)的操作吏垮,不需要將本次請求的相關(guān)信息記錄下來以便用于后續(xù)來自相同客戶端請求的處理障涯。REST 獨立于任何基礎(chǔ)協(xié)議,并且不一定綁定到 HTTP膳汪。由于HTTP協(xié)議本身就是無狀態(tài)的唯蝶, 最常見的 REST 實現(xiàn)使用 HTTP 作為應(yīng)用程序協(xié)議。
遇到的挑戰(zhàn)
RESTful的設(shè)計風(fēng)格可以極大提高接口的易用性遗嗽,目前已經(jīng)越來越多的web服務(wù)已經(jīng)采用RESTful風(fēng)格的API對外提供服務(wù)粘我,例如:ElasticSearch、MongoDB痹换、Docker等征字。作為一名后臺開發(fā)工程師都弹,我在實際工作中也是以RESTful風(fēng)格指導(dǎo)自己進行接口設(shè)計的過程中,主要會遇到以下兩個問題:
某些接口無法抽象為資源匙姜,例如:登入接口畅厢、登出接口、搜索接口等氮昧。實際工作中經(jīng)常會遇到這樣的接口:這些接口是針對資源的操作行為框杜,而無法抽象為一種新的資源。ElasticSearch對外提供了非常完善的RESTful風(fēng)格的API郭计,但是針對搜索操作霸琴,用到的URI卻是
/index/doc/_search
椒振。參照這種方式昭伸,我在工作中如果需要提供類似的接口,也會提供包含動作含義的URI澎迎。另一個棘手的問題是RESTful風(fēng)格的API在框架層面不好做監(jiān)控庐杨。通常情況下監(jiān)控為了不侵入業(yè)務(wù)代碼,框架層面記錄每個HTTP請求的URI夹供、方法灵份、返回狀態(tài)碼等信息,然后上報至一個統(tǒng)一的監(jiān)控中心處理分析數(shù)據(jù)哮洽。以查詢雇員信息的API為例填渠,
GET /employees/c001
和GET /employees/c002
分別代表查詢c001和c002的信息,業(yè)務(wù)層面上使用了同一份查詢代碼鸟辅,但是監(jiān)控數(shù)據(jù)卻顯示在兩個不同的URI下氛什。目前我們的解決方案是在業(yè)務(wù)層面為每個API配置一條監(jiān)控的URI,這樣GET /employees/c001
和GET /employees/c002
這兩種請求的監(jiān)控都會現(xiàn)在查詢雇員信息API下匪凉,這樣可以更容易反應(yīng)服務(wù)執(zhí)行狀態(tài)枪眉。但是導(dǎo)致的結(jié)果就是工作量的增加,本來在框架層面可以統(tǒng)一處理的邏輯卻要侵入至業(yè)務(wù)代碼再层。
結(jié)論
REST不僅可以對外提供易用方便的API贸铜,同時面向資源的設(shè)計風(fēng)格可以指導(dǎo)數(shù)據(jù)層面上的領(lǐng)域建模,在實際工作中非常值得推薦聂受。但是REST風(fēng)格的API也會帶來一些新的挑戰(zhàn)蒿秦,我們沒必要做一個死板的REST原教旨主語者,應(yīng)該根據(jù)場景蛋济,靈活運用棍鳖,最大程度保證接口定義的清晰明了以及功能的穩(wěn)定正常。
參考資料
[1] 淺談RESTful接口設(shè)計和開發(fā) http://www.reibang.com/p/d674b6153326
[2] 我所理解的RESTful Web API [設(shè)計篇] https://www.cnblogs.com/artech/p/restful-web-api-02.html
[3] Web API 設(shè)計 https://docs.microsoft.com/zh-cn/azure/architecture/best-practices/api-design