- 前言
-
- REST是什么
- 2.1改艇、起源
- 2.2兰粉、REST架構(gòu)的標(biāo)志
- 2.3、超媒體(hypermedia)
- 2.4恋昼、REST誤解]
-
- REST 架構(gòu)風(fēng)格的推導(dǎo)過程
- 3.1. REST 所繼承的架構(gòu)風(fēng)格約束
- 3.2. 在論文中推導(dǎo)出的 REST 架構(gòu)風(fēng)格圖示
- 3.3. 一個(gè)基于 REST 的架構(gòu)的過程視圖(包括HTTP/1.1應(yīng)用實(shí)踐)]
-
- 為什么要用RESTful]
- 4.1 常見的三種分布式應(yīng)用架構(gòu)風(fēng)格
- 4.2 REST和DO對(duì)比
- 4.3 REST與RPC對(duì)比]
- RESTful如何設(shè)計(jì)
- 各端的具體實(shí)現(xiàn)]
- Django REST Framework使用
1.前言
在「遠(yuǎn)古時(shí)代」前端后端是融合在一起的看靠,比如之前的PHP,JSP焰雕,ASP等等衷笋。近年來隨著移動(dòng)互聯(lián)網(wǎng)的飛速發(fā)展,各種類型的Client端層出不窮矩屁,就需要通過一套統(tǒng)一的接口分別為Web辟宗,iOS和Android乃至桌面端提供服務(wù)。另外對(duì)于廣大平臺(tái)來說吝秕,比如Facebook platform泊脐,微博開放平臺(tái),微信烁峭、QQ公共平臺(tái)等容客,它們不需要有顯式的前端,只需要一套提供服務(wù)的接口约郁,于是RESTful更是它們最好的選擇缩挑。
2.RESTful是什么
越來越多的人開始意識(shí)到,網(wǎng)站即軟件鬓梅,而且是一種新型的軟件供置。
這種"互聯(lián)網(wǎng)軟件"采用客戶端/服務(wù)器模式,建立在分布式體系上绽快,通過互聯(lián)網(wǎng)通信芥丧,具有高延時(shí)紧阔、高并發(fā)等特點(diǎn)。
網(wǎng)站開發(fā)续担,完全可以采用軟件開發(fā)的模式擅耽。但是傳統(tǒng)上,軟件和網(wǎng)絡(luò)是兩個(gè)不同的領(lǐng)域物遇,很少有交集乖仇;軟件開發(fā)主要針對(duì)單機(jī)環(huán)境,網(wǎng)絡(luò)則主要研究系統(tǒng)之間的通信询兴≌饩矗互聯(lián)網(wǎng)的興起,使得這兩個(gè)領(lǐng)域開始融合蕉朵,現(xiàn)在我們必須考慮,如何開發(fā)在互聯(lián)網(wǎng)環(huán)境中使用的軟件阳掐。
RESTful架構(gòu)始衅,就是目前最流行的一種互聯(lián)網(wǎng)軟件架構(gòu)。它結(jié)構(gòu)清晰缭保、符合標(biāo)準(zhǔn)汛闸、易于理解、擴(kuò)展方便艺骂,所以正得到越來越多網(wǎng)站的采用诸老。
需要注意的是,REST是一種設(shè)計(jì)風(fēng)格而不是標(biāo)準(zhǔn)钳恕,如果一個(gè)架構(gòu)符合REST原則别伏,我們就稱它為RESTful架構(gòu)。
2.1忧额、起源
在互聯(lián)網(wǎng)行業(yè)厘肮,實(shí)踐總是走在理論的前面。Web 發(fā)展到了 1995 年睦番,在 CGI类茂、ASP 等技術(shù)出現(xiàn)之后,沿用了多年托嚣、主要面向靜態(tài)文檔的 HTTP/1.0 協(xié)議已經(jīng)無法滿足 Web 應(yīng)用的開發(fā)需求巩检,因此需要設(shè)計(jì)新版本的 HTTP 協(xié)議。在 HTTP/1.0 協(xié)議專家組之中示启,有一位年輕人脫穎而出兢哭,顯示出了不凡的洞察力,后來他成為了 HTTP/1.1 協(xié)議專家組的負(fù)責(zé)人丑搔。這位年輕人就是 Apache HTTP 服務(wù)器的核心開發(fā)者 Roy Fielding厦瓢,他還是 Apache 軟件基金會(huì)的合作創(chuàng)始人提揍。
Roy Fielding 和他的同事們?cè)?HTTP/1.1 協(xié)議的設(shè)計(jì)工作中,對(duì)于 Web 之所以取得巨大成功煮仇,在技術(shù)架構(gòu)方面的因素做了一番深入的總結(jié)劳跃。Fielding 將這些總結(jié)納入到了一套理論框架之中,然后使用這套理論框架中的指導(dǎo)原則浙垫,來指導(dǎo) HTTP/1.1 協(xié)議的設(shè)計(jì)方向刨仑。HTTP/1.1 協(xié)議的第一個(gè)草稿是在 1996 年 1 月發(fā)布的,經(jīng)過了三年多時(shí)間的修訂夹姥,于 1999 年 6 月成為了 IETF 的正式規(guī)范(包括了 RFC 2616 以及用于對(duì)客戶端做身份認(rèn)證的 RFC 2617)杉武。HTTP/1.1 協(xié)議設(shè)計(jì)的極為成功,以至于發(fā)布之后整整 10 年時(shí)間里辙售,都沒有多少人認(rèn)為有修訂的必要轻抱。用來指導(dǎo) HTTP/1.1 協(xié)議設(shè)計(jì)的這套理論框架,最初是以備忘錄的形式在專家組成員之間交流旦部,除了 IETF/W3C 的專家圈子祈搜,并沒有在外界廣泛流傳。Fielding 在完成 HTTP/1.1 協(xié)議的設(shè)計(jì)工作之后士八,回到了加州大學(xué)歐文分校繼續(xù)攻讀自己的博士學(xué)位容燕。
第二年(2000 年)在他的博士學(xué)位論文 Architectural Styles and the Design of Network-based Software Architectures 中,F(xiàn)ielding 更為系統(tǒng)婚度、嚴(yán)謹(jǐn)?shù)仃U述了這套理論框架蘸秘,并且使用這套理論框架推導(dǎo)出了一種新的架構(gòu)風(fēng)格,并且為這種架構(gòu)風(fēng)格取了一個(gè)費(fèi)解難懂名字“REST”蝗茁,即Representational State Transfer(表現(xiàn)層狀態(tài)轉(zhuǎn)化醋虏,一般是這個(gè)翻譯,但你聽聽這是人話嗎评甜?)的縮寫.應(yīng)該是缺少了主語灰粮。全稱是 Resource Representational State Transfer:通俗來講就是:資源在網(wǎng)絡(luò)中以某種表現(xiàn)形式進(jìn)行狀態(tài)轉(zhuǎn)移。分解開來:
Resource: 資源忍坷,即數(shù)據(jù)
Representional:某種表現(xiàn)形式粘舟,比如xml,json.
State Transfer:狀態(tài)變化佩研。通過HTTP動(dòng)詞實(shí)現(xiàn)柑肴。
2.2、REST架構(gòu)的標(biāo)志
根據(jù)理查德森模型,REST架構(gòu)的成熟度有3分等級(jí)
-
Level 0 POX(這個(gè)就不算REST了)旬薯。
- 這類應(yīng)用只有一個(gè)URL上的上帝接口晰骑,根據(jù)交換的XML內(nèi)容操作所有的資源,往往導(dǎo)致上帝接口越來越復(fù)雜,越來越難維護(hù)硕舆。
-
Level 1 Resource秽荞。
- 這一級(jí)別主要解決了上帝接口的問題,使得各種資源有了自己相應(yīng)URL抚官,雖然仍然是POX的交互方式扬跋,但每一個(gè)接口都更加緊湊和內(nèi)聚,相應(yīng)的容易維護(hù)起來凌节。
- URL templating帶來的結(jié)果是服務(wù)器端和客戶端的緊耦合钦听,任何時(shí)候服務(wù)器端想改變自身的URL scheme的時(shí)候,都要break已經(jīng)存在的客戶端應(yīng)用倍奢。
- URL tunneling帶來的問題包含URL templating,而且放棄了使用HTTP協(xié)議標(biāo)準(zhǔn)帶來的任何好處(level2中詳述)朴上。
- 早期的rails routes就是url templating/tunneling。Rails3開始已經(jīng)更新更加靠近level 2了卒煞。
-
Level 2 Http verbs
這一級(jí)別的使用http verbs來對(duì)各種資源進(jìn)行CRUD操作痪宰,使得應(yīng)用程序的接口更加統(tǒng)一,語義個(gè)更加明確畔裕。同時(shí)應(yīng)為遵照http協(xié)議的標(biāo)準(zhǔn)進(jìn)行交互酵镜,很多http提供的好處幾乎可以免費(fèi)的得到。此時(shí)使用多個(gè)URI的話柴钻,需要讓不同的URI代表不同的資源(注意多個(gè)URI可能指向同一個(gè)Resource,而一個(gè)URI不能指向不同Resource婉商。)渤早,同時(shí)使用多個(gè)HTTP方法操作這些資源躬络,例如使用POST/GET/PUT/DELET分別進(jìn)行CRUD操作。這時(shí)候HTTP頭和有效載荷都包含業(yè)務(wù)邏輯毫蚓,例如HTTP方法對(duì)應(yīng)CRUD操作,HTTP狀態(tài)碼對(duì)應(yīng)操作結(jié)果的狀態(tài)昔善。
-
Cache
- 按照HTTP協(xié)議元潘,GET操作是安全的,冪等(idempotent)的君仆,任意多次對(duì)同一資源的GET操作翩概,都不會(huì)導(dǎo)致資源的狀態(tài)變化。所以GET的結(jié)果是可以安全的cache 返咱。所有http提供的cache facilities都可以被利用起來钥庇,大幅度提高了應(yīng)用程序的性能。甚至你僅僅只是在response里面加上cache directives就可以免費(fèi)獲得網(wǎng)絡(luò)上各級(jí)的緩存服務(wù)器咖摹,代理服務(wù)器评姨,以及用戶客戶端的緩存支持∮┣纾互聯(lián)網(wǎng)上幾乎所有的應(yīng)用你都可以粗略統(tǒng)計(jì)得到Get VS Non-Get的請(qǐng)求比例約為4:1吐句,如果你能為GET操作加上緩存胁后,將極大的提升你的程序性能。
-
Robust
- 在HTTP常用的幾個(gè)動(dòng)詞里嗦枢,HRAD攀芯,GET,PUT净宵,DELETE是安全的敲才,冪等的。因?yàn)閷?duì)同一資源的任一多次請(qǐng)求择葡,永遠(yuǎn)代表同一語義紧武,所以任何時(shí)候客戶端發(fā)送出去這些動(dòng)詞的時(shí)候,如果服務(wù)器沒有響應(yīng)敏储,或者返回錯(cuò)誤代碼阻星,客戶端都可以非常安全的再執(zhí)行一次同一操作而不是擔(dān)心重復(fù)操作帶來的不同語義及最終結(jié)果。POST已添,PATCH就不是安全的妥箕,因?yàn)榭蛻舳讼蚍?wù)器端發(fā)送請(qǐng)求之后,服務(wù)器沒有響應(yīng)或者返回錯(cuò)誤代碼更舞,客戶端是不能安全的重復(fù)操作的畦幢,一定只是從新與服務(wù)器確認(rèn)現(xiàn)在的資源狀態(tài)才能決定下一步的操作。
絕大部分的RESTful應(yīng)用就停在這里了缆蝉,當(dāng)然也滿足了大多的需求宇葱。
-
-
Level 3 Hypermedia controls
RESTful的架構(gòu)本意是“在符合架構(gòu)原理的前提下,理解和評(píng)估以網(wǎng)絡(luò)為基礎(chǔ)的應(yīng)用軟件的架構(gòu)設(shè)計(jì)刊头,得到一個(gè)功能強(qiáng)黍瞧,性能好,適宜通信的架構(gòu)”原杂。
-
目前規(guī)模最大印颤,耦合度最低、最穩(wěn)定的穿肄、性能最好的分布式網(wǎng)絡(luò)應(yīng)用是什么年局?就是WEB本身。 規(guī)模咸产、穩(wěn)定某宪、性能都不用說,為什么耦合度低呢锐朴?想想每個(gè)人上網(wǎng)的經(jīng)歷兴喂,你幾乎不需要什么任何培訓(xùn)就可以上一個(gè)新的網(wǎng)絡(luò)購物平臺(tái)挑選商品,用信用卡付款,郵到自己家里畏鼓。把網(wǎng)站的程序想象成一個(gè)狀態(tài)機(jī),用戶在一系列的狀態(tài)轉(zhuǎn)換中完成自己的目標(biāo)壶谒,中間的每一步云矫,用用程序都告訴你當(dāng)前的狀態(tài)和可能的下一步操作,最終引導(dǎo)用戶從挑選商品到付款郵寄到家汗菜,到達(dá)狀態(tài)機(jī)的終點(diǎn)让禀。
這種service discoverability和self-documenting就是Level 3想解決的問題。
在這里面陨界,告訴用戶當(dāng)前的狀態(tài)以及各種下一步操作的東西巡揍,例如鏈接,按鈕等等菌瘪,就是Hypermedia Controls腮敌。Hypermedia Controls 就是這個(gè)狀態(tài)機(jī)的引擎。
Level 3的REST架構(gòu)就是希望能夠統(tǒng)一這一類的Hypermedia Controls, 賦予他們標(biāo)準(zhǔn)的, 高度可擴(kuò)展的標(biāo)準(zhǔn)語義及表現(xiàn)形式, 使得甚至無人工干預(yù)的機(jī)器與機(jī)器間的通用交互協(xié)議邊的可能. 比如你可以告訴一個(gè)通用的購物客戶端, "給我買個(gè)最便宜的xbox", 客戶端自動(dòng)連上google進(jìn)行搜索, 自動(dòng)在前10個(gè)購物網(wǎng)站進(jìn)行搜索, 進(jìn)行價(jià)格排序, 然后自動(dòng)挑選最便宜的網(wǎng)站, 進(jìn)行一系列操作最終完成用信用卡付費(fèi), 填寫個(gè)人收件地址然后郵寄.
這些都依賴于Hypermedia Controls帶來的這種service discoverablility和self-documenting
當(dāng)然另外一種更簡(jiǎn)便的總結(jié)式可以這樣理解:
-
REST四個(gè)基本原則:
- 使用HTTP動(dòng)詞:GET俏扩、 POST 糜工、PUT 、DELETE录淡;
- 無狀態(tài)連接捌木,服務(wù)器端不應(yīng)保存過多上下文狀態(tài),即每個(gè)請(qǐng)求都是獨(dú)立的嫉戚;
- 為每個(gè)資源設(shè)置URI钮莲;
- 通過XML JSON進(jìn)行數(shù)據(jù)傳遞;
實(shí)現(xiàn)上述原則的架構(gòu)即可稱為RESTFul架構(gòu)彼水。
- 互聯(lián)網(wǎng)環(huán)境下,任何應(yīng)用的架構(gòu)和API可以被快速理解极舔;
- 分布式環(huán)境下凤覆,任何請(qǐng)求都可以被發(fā)送到任意服務(wù)器;
- 異構(gòu)環(huán)境下拆魏,任何資源的訪問和使用方式都統(tǒng)一盯桦;
RESTful簡(jiǎn)單來說就是:URL定位資源,用HTTP動(dòng)詞(GET,POST,DELETE,DETC)描述操作渤刃。
2.3拥峦、超媒體(hypermedia)
根據(jù)Roy的嚴(yán)格規(guī)定,超媒體(hypermedia)是REST的先決條件卖子,任何其他東西都不應(yīng)該自我標(biāo)榜為REST略号,這里要要先解釋一個(gè)概念:超媒體,wiki上面有這樣一個(gè)解釋:
多媒體(Multimedia),在電腦應(yīng)用系統(tǒng)中玄柠,組合兩種或兩種以上媒體的一種人機(jī)交互式資訊交流和傳播媒體突梦。使用的媒體包括文字、圖片羽利、照片宫患、聲音(包含音樂、語音旁白这弧、特殊音效)娃闲、動(dòng)畫和影片,以及程序所提供的互動(dòng)功能匾浪。
超媒體(Hypermedia)是多媒體系統(tǒng)中的一個(gè)子集皇帮,超媒體系統(tǒng)是使用超鏈接(Hyperlink)構(gòu)成的全球資訊系統(tǒng),全球資訊系統(tǒng)是互聯(lián)網(wǎng)上使用TCP/IP協(xié)議和UDP/IP協(xié)議的應(yīng)用系統(tǒng)户矢。2D的多媒體網(wǎng)頁使用HTML玲献、XML等語言編寫,3d的多媒體網(wǎng)頁使用VRML等語言編寫梯浪。目前許多多媒體作品使用光碟發(fā)行捌年,以后將更多地使用網(wǎng)絡(luò)發(fā)行。
此種關(guān)鍵的角色還是超鏈接挂洛,使用超媒體作為應(yīng)用引擎狀態(tài)礼预,意思是應(yīng)用引擎狀態(tài)變更,由客戶端訪問不同的超媒體資源驅(qū)動(dòng)虏劲。
如下示例:
GET :https://api.github.com/authorizations
{
"author": "github",
"video": {
"large": "https://api.github.com/Japan/large.avi.png",
"medium": "https://api.github.com/Japan/media.avi.png",
"small": "https://api.github.com/Japan/small.avi.png"
}
}
由于在響應(yīng)中包含了鏈接地址托酸,因此使用該API的客戶端就能夠自由選擇要下載怎樣的信息。這些鏈接告知了客戶端有哪些選擇柒巫,并且它們的地址在哪里励堡。
因此在這里我們無需同時(shí)返回三個(gè)不同版本小視頻,我們所做的只是告訴客戶端有三種不同清晰度可以選擇堡掏,并且告訴客戶端能夠在哪里找到這些avi应结。
這樣一來,客戶端就能夠根據(jù)不同的場(chǎng)景泉唁,做出符合自身需要的選擇鹅龄。而且,如果客戶端只需要一種高清無碼格式的亭畜,那就無需下載全部三種扮休。這樣一來可謂一箭三雕:既減少了網(wǎng)絡(luò)負(fù)載,又增進(jìn)了客戶端的靈活性拴鸵,更增進(jìn)了API的可探索性玷坠。
超媒體的核心概念就是所謂的元素蜗搔,而這些相互鏈接的資源實(shí)際上描述了一個(gè)協(xié)議,即引導(dǎo)我們達(dá)成某個(gè)目標(biāo)的一系列步驟:
例如訂購一杯咖啡所需要的點(diǎn)單侨糟、付款碍扔、取咖啡等等。這就是超媒體的本質(zhì):經(jīng)由資源之間的鏈接秕重,我們改變整個(gè)應(yīng)用的狀態(tài)不同,即超媒體轉(zhuǎn)換了,分布式應(yīng)用的狀態(tài)溶耘。需要注意的是二拐,服務(wù)器和消費(fèi)者兩者間,交換的是資源狀態(tài)的表述凳兵,而不是應(yīng)用的狀態(tài)百新,被轉(zhuǎn)移的表述中,包括了反應(yīng)庐扫,應(yīng)用狀態(tài)的鏈接饭望。
2.4、REST誤解
現(xiàn)在看來形庭,REST在2000年那個(gè)時(shí)代铅辞,確實(shí)是超前于時(shí)代的。Web開發(fā)者社區(qū)對(duì)于HTTP的設(shè)計(jì)意圖存在著大量的誤解萨醒,由此導(dǎo)致了對(duì)于HTTP的大量低效率的誤用斟珊。這個(gè)情況持續(xù)一直到2005年Web 2.0的崛起。那個(gè)時(shí)候富纸,DCOM囤踩、EJB、SOAP/WSDL這些DO風(fēng)格的架構(gòu)由于難以滿足互聯(lián)網(wǎng)環(huán)境對(duì)分布式應(yīng)用架構(gòu)設(shè)計(jì)的約束晓褪,與Web自身的架構(gòu)風(fēng)格REST相沖突堵漱,很難融入到Web之中。所謂的「Web Services」涣仿,其實(shí)除了將HTTP作為底層的傳輸協(xié)議外勤庐,跟(互聯(lián)網(wǎng)環(huán)境中的)真正的Web沒有什么關(guān)系。
而隨著Ruby on Rails這個(gè)著名的Web開發(fā)框架開始大力支持REST開發(fā)之后变过,一線的Web開發(fā)者才真正接觸到了REST。然而Rails所支持的REST開發(fā)將對(duì)資源的操作局限于CRUD(創(chuàng)建涝涤、獲取媚狰、修改、刪除)的語義(即阔拳,將對(duì)資源的CRUD操作映射到 GET/POST/PUT/DELETE四個(gè)HTTP方法)崭孤,這其實(shí)是收窄了REST的適用范圍类嗤。其他編程語言的Web開發(fā)框架(例如Java語言的 Struts、Spring MVC等等)也緊接著模仿了Rails的方式開始支持REST開發(fā)辨宠,然而這更加導(dǎo)致了一線的Web開發(fā)者誤以為:REST開發(fā)就是 通過GET/POST/PUT/DELETE四個(gè)HTTP方法對(duì)資源執(zhí)行CRUD操作遗锣。甚至還有很多僅僅使用了HTTP,而沒有使用SOAP的Web服 務(wù)API嗤形,都自稱是REST風(fēng)格(RESTful)的API精偿。
對(duì)于什么才是真正的REST風(fēng)格的誤解是如此之多,而將REST作為一個(gè)便于營(yíng)銷的 buzzword的掛羊頭賣狗肉者也是如此之多赋兵,以至于REST的創(chuàng)造者Fielding終于忍無可忍了笔咽。2008年10月Fielding寫了一篇博 客,做出了一個(gè)非常明確的斷言:REST APIs must be hypertext-driven!(REST API必須是超文本驅(qū)動(dòng)的E凇)超文本驅(qū)動(dòng)這個(gè)理念變成了一個(gè)縮寫詞HATEOAS叶组,這個(gè)縮寫詞來自于當(dāng)初Fielding博士論文中的一句話: hypermedia as the engine of application state(將超媒體作為應(yīng)用狀態(tài)的引擎)。
其實(shí)超文本驅(qū)動(dòng)(Hypertext Driven)的理念才是REST架構(gòu)風(fēng)格最核心的理念历造,也是REST風(fēng)格的架構(gòu)達(dá)到松耦合目標(biāo)的根本原因甩十。
3.REST 架構(gòu)風(fēng)格的推導(dǎo)過程
3.1 REST 所繼承的架構(gòu)風(fēng)格約束(圖 1)
在圖 1 中,每一個(gè)橢圓形里面的縮寫詞代表了一種架構(gòu)風(fēng)格吭产,而每一個(gè)箭頭邊的單詞代表了一種架構(gòu)約束侣监。
- REST 架構(gòu)風(fēng)格最重要的架構(gòu)約束有 6 個(gè):
-
客戶-服務(wù)器(Client-Server)
通信只能由客戶端單方面發(fā)起,表現(xiàn)為請(qǐng)求--響應(yīng)模式垮刹。
-
無狀態(tài)(Stateless)
通信會(huì)話狀態(tài)(Session State)應(yīng)該全部有客戶端負(fù)責(zé)維護(hù)达吞。
-
緩存(Cache)
響應(yīng)內(nèi)容可以在通信連接的某處緩存,以改善網(wǎng)絡(luò)效率
-
統(tǒng)一接口(Uniform Interface)
通信鏈的組件之間通過統(tǒng)一的接口相互通信荒典,以提高交互的可見性酪劫。
-
分層系統(tǒng)(Layered System)
通過限制組件的行為(即,每個(gè)組件只能“看到”與其交互的緊鄰層)寺董,將結(jié)構(gòu)分解成若干等級(jí)覆糟。
-
按需代碼(Code-On—Demand,可選)
通過支持下載并執(zhí)行一些代碼(例如:Java Applet,F(xiàn)lash或者JS)遮咖,對(duì)客戶端的功能進(jìn)行擴(kuò)展滩字。
-
3.2. 在論文中推導(dǎo)出的 REST 架構(gòu)風(fēng)格如下圖所示:
3.3 .一個(gè)基于 REST 的架構(gòu)的過程視圖
而 HTTP/1.1 協(xié)議作為一種 REST 架構(gòu)風(fēng)格的架構(gòu)實(shí)例,其架構(gòu)如下圖所示:
用戶代理處在三個(gè)并行交互(a麦箍、b 和 c)的中間。用戶代理的客戶端連接器緩存無法滿足請(qǐng)求陶珠,因此它根據(jù)每個(gè)資源標(biāo)識(shí)符的屬性和客戶端連接器的配置挟裂,將每個(gè)請(qǐng)求路由到資源的來源。
請(qǐng)求(a)被發(fā)送到一個(gè)本地代理揍诽,代理隨后訪問一個(gè)通過 DNS 查找發(fā)現(xiàn)的緩存網(wǎng)關(guān)诀蓉,該網(wǎng)關(guān)將這個(gè)請(qǐng)求轉(zhuǎn)發(fā)到一個(gè)能夠滿足該請(qǐng)求的來源服務(wù)器栗竖,服務(wù)器的內(nèi)部資源由一個(gè)封裝過的對(duì)象請(qǐng)求代理(object request broker)架構(gòu)來定義。
請(qǐng)求(b)直接發(fā)送到一個(gè)來源服務(wù)器渠啤,它能夠通過自己的緩存來滿足這個(gè)請(qǐng)求狐肢。
請(qǐng)求(c)被發(fā)送到一個(gè)代理,它能夠直接訪問 WAIS(一種與 Web 架構(gòu)分離的信息服務(wù))沥曹,并將 WAIS 的響應(yīng)翻譯為一種通用的連接器接口能夠識(shí)別的格式份名。每一個(gè)組件只知道與它們自己的客戶端或服務(wù)器連接器的交互;
4. 為什么要用RESTful結(jié)構(gòu)呢架专?
4.1. 從架構(gòu)風(fēng)格的抽象角度來看同窘,常見的分布式應(yīng)用架構(gòu)風(fēng)格有三種:
-
1.分布式對(duì)象(Distributed Objects,簡(jiǎn)稱DO)
架構(gòu)實(shí)例有 CORBA/RMI/EJB/DCOM/.NET Remoting 等等
-
2.遠(yuǎn)程過程調(diào)用(Remote Procedure Call部脚,簡(jiǎn)稱RPC)
架構(gòu)實(shí)例有 SOAP/XML-RPC/Hessian/Flash AMF/DWR 等等
-
3.表現(xiàn)層狀態(tài)轉(zhuǎn)移(Representational State Transfer想邦,簡(jiǎn)稱REST)
架構(gòu)實(shí)例有HTTP/1.1、WebDav
DO 和 RPC 這兩種架構(gòu)風(fēng)格在企業(yè)應(yīng)用中非常普遍委刘,而 REST 則是 Web 應(yīng)用的架構(gòu)風(fēng)格丧没,它們之間有非常大的差別。
4.2. REST和DO的差別在于:
REST支持抽象(即建模)的工具是資源锡移。DO支持抽象的工具是對(duì)象呕童。在不同的編程語言中,對(duì)象的定義有很大的差別淆珊,所以DO風(fēng)格的架構(gòu)通常都是與某種編程語言綁定的夺饲。跨語言交互即使能實(shí)現(xiàn)施符,實(shí)現(xiàn)是來也是會(huì)很復(fù)雜往声。而REST中的資源,則完全中立與開發(fā)平臺(tái)和編程語言戳吝,可以使用任何編程語言來實(shí)現(xiàn)浩销。
DO中沒有統(tǒng)一接口的概念。不同API听哭,接口風(fēng)格可以完全不同慢洋。DO也不支持操作語義對(duì)于中間件的可見性。
DO中沒有使用超文本陆盘,響應(yīng)的內(nèi)容只包含對(duì)象本身普筹。REST使用了超媒體,可以實(shí)現(xiàn)更大顆粒度的交互隘马,交互的效率比DO高太防。
REST支持?jǐn)?shù)據(jù)流和管道,DO不支持?jǐn)?shù)據(jù)流和管道祟霍。
DO風(fēng)格通常會(huì)來來客戶端和服務(wù)端的緊耦合杏头。在三種架構(gòu)風(fēng)格之中,DO風(fēng)格的耦合度是最大的沸呐,而REST的風(fēng)格耦合度是最小的醇王。REST松偶合的來源來自統(tǒng)一接口 + 超媒體驅(qū)動(dòng)。
4.3. REST與RPC的差別在于:
REST支持抽象的工具是資源崭添,RPC支持抽象工具是過程寓娩。REST風(fēng)格架構(gòu)建模是以名詞為核心的,RPC風(fēng)格的架構(gòu)建模是以動(dòng)詞為核心的呼渣。簡(jiǎn)單類比一下棘伴,REST是面向?qū)ο缶幊蹋琑PC則是面向過程編程屁置。
RPC中沒有統(tǒng)一的接口概念焊夸。不同的API,接口設(shè)計(jì)風(fēng)格可以完全不同蓝角,RPC也不支持語義對(duì)于中間件的可見性阱穗。
RPC沒有使用超媒體,響應(yīng)的內(nèi)容中只包含消息本身使鹅。REST使用了超媒體揪阶,可以實(shí)現(xiàn)更大顆粒度的交互效率也更高。
REST支持?jǐn)?shù)據(jù)流和管道患朱,RPC不支持?jǐn)?shù)據(jù)流和管道
因?yàn)槭褂昧似脚_(tái)中立的消息鲁僚。RPC風(fēng)格耦合度比DO風(fēng)格小一些,但是RPC風(fēng)格也常常會(huì)帶來客戶端和服務(wù)器的緊耦合裁厅。支持統(tǒng)一接口+超媒體驅(qū)動(dòng)的風(fēng)格冰沙,可以達(dá)到最小的耦合度
4.4. REST 架構(gòu)風(fēng)格優(yōu)越之處:
比較了三種架構(gòu)風(fēng)格之間的差別之后,從面向?qū)嵱玫慕嵌葋砜唇阒保琑EST 架構(gòu)風(fēng)格可以為 Web 開發(fā)者帶來三方面的利益:
- 簡(jiǎn)單性
采用REST架構(gòu)風(fēng)格倦淀,對(duì)于開發(fā)、測(cè)試声畏、運(yùn)維人員來說都會(huì)更簡(jiǎn)單撞叽。可以充分利用大量HTTP服務(wù)端和客戶端開發(fā)庫插龄、Web功能測(cè)試/性能測(cè)試工具愿棋、HTTP緩存、HTTP代理服務(wù)器均牢、防火墻糠雨。這些開發(fā)庫和基礎(chǔ)設(shè)施早已成為日常用品,不需要什么高科技(例如神奇昂貴的應(yīng)用服務(wù)器徘跪、中間件)就能解決大多數(shù)可伸縮性方面的問題甘邀。
- 可伸縮性
充分利用好通訊鏈各個(gè)位置的HTTP緩存組件琅攘,可以帶來更好的伸縮性。其實(shí)很多時(shí)候松邪,在Web前端做性能優(yōu)化坞琴,產(chǎn)生的效果不亞于僅僅在服務(wù)器端做性能優(yōu)化,但是HTTP協(xié)議層面的緩存常常被一些看似很牛逼的人給忽略掉了逗抑。
- 松耦合
統(tǒng)一接口 + 超媒體引擎驅(qū)動(dòng)剧辐,帶來了最大限度的松耦合。允許服務(wù)器和客戶端在很大范圍內(nèi)邮府,相對(duì)獨(dú)立的運(yùn)行荧关。對(duì)于設(shè)計(jì)面向企業(yè)內(nèi)網(wǎng)的API來說,松耦合并不是一個(gè)很重要的設(shè)計(jì)關(guān)注點(diǎn)褂傀。但是對(duì)于設(shè)計(jì)面向互聯(lián)網(wǎng)的API來說忍啤,松耦合成了一個(gè)必選項(xiàng),不僅僅在設(shè)計(jì)時(shí)應(yīng)該關(guān)注仙辟,而且應(yīng)該昂在最優(yōu)的位子檀轨。
下面這段話出自知乎覃超,是一個(gè)淺顯易懂的總結(jié):
大家都知道"古代"網(wǎng)頁都是前端后端融在一起的,比如之前的PHP欺嗤,JSP等参萄。在之前的桌面時(shí)代問題不大,但是近年來移動(dòng)互聯(lián)網(wǎng)的發(fā)展煎饼,各種類型的Client層出不窮讹挎,RESTful可以通過一套統(tǒng)一的接口為 Web,iOS和Android提供服務(wù)吆玖。另外對(duì)于廣大平臺(tái)來說筒溃,比如Facebook platform,微博開放平臺(tái)沾乘,微信公共平臺(tái)等怜奖,它們不需要有顯式的前端,只需要一套提供服務(wù)的接口翅阵,于是RESTful更是它們最好的選擇歪玲。在RESTful架構(gòu)下:
5. RESTful如何設(shè)計(jì)
-
1、協(xié)議
- api與用戶的通訊協(xié)議掷匠,HTTP/HTTPS滥崩。
-
2、域名
-
應(yīng)盡量將API部署在專用域名之下讹语。
https://api.example.com
-
如果確定API很簡(jiǎn)單钙皮,不會(huì)有修改和進(jìn)一步的擴(kuò)展,可以考慮放在主域名下。
https://example.com/api/...
-
-
3短条、版本號(hào)
-
版本號(hào)放入U(xiǎn)LR或者HTTP頭的信息中
https://api.example.com/v1/...
-
-
4导匣、路徑
在RESTful的架構(gòu)中,每個(gè)網(wǎng)址代表著一種資源(resource),所以一個(gè)好的設(shè)計(jì)中茸时,網(wǎng)址中不要有動(dòng)詞逐抑,只能用名詞。其實(shí)「資源」表示一種實(shí)體屹蚊,所以應(yīng)該是名詞,動(dòng)詞應(yīng)該放在HTTP協(xié)議中进每。而與此同時(shí)URI也有可能破壞HTTP GET的安全性和幕等性汹粤,比如某個(gè)客戶端在
http://example.com/updateOrder?id=1234&coffee=latte
上執(zhí)行GET(而不是POST),就能創(chuàng)建一筆新的咖啡訂單(一個(gè)資源)田晚,按理來說GET請(qǐng)求不能改變服務(wù)的任何狀態(tài)嘱兼。而且所用名詞往往與數(shù)據(jù)庫中的表格對(duì)應(yīng)。一般來說贤徒,數(shù)據(jù)庫中的表都是同種記錄的集合“集合”芹壕。
例如:API提供動(dòng)物園(zoo)的信息,可以這樣設(shè)計(jì)接奈;https://api.example.com/v1/zoos https://api.example.com/v1/animals https://api.example.com/v1/dogs
-
5踢涌、HTTP動(dòng)詞
- GET :用來獲取資源,
- POST :用來新建資源(也可以用于更新資源)序宦,
- PUT :用來更新資源睁壁,
- DELETE :用來刪除資源。
- PATCH(UPDATE):在服務(wù)器更新資源(客戶端提供改變的屬性)互捌。
- HEAD:獲取資源的元數(shù)據(jù)潘明。
- PTIONS:獲取信息,關(guān)于資源的哪些屬性是客戶端可以改變的秕噪。
-
6钳降、過濾信息
如果記錄數(shù)量很多,服務(wù)器不可能都將他們返回給用戶腌巾。API提供參數(shù)返回過濾后的數(shù)據(jù):
* ?limit=10:指定返回記錄的數(shù)量 * ?offset=10:指定返回記錄開始的位置 * ?page-2&per_page=100:指定第幾頁以及每頁的返回?cái)?shù)量 * ?sortby=name&order=asc:指定返回結(jié)果按照哪個(gè)屬性排序遂填,以及排序順序 * ?animal_type_id=1:指定篩選條件
參數(shù)的設(shè)計(jì)允許存在冗余,即允許API路徑和URL參數(shù)偶爾有重復(fù)澈蝙。比如城菊,GET /zoo/ID/animals 與 GET /animals?zoo_id=ID 的含義是相同的。
7碉克、狀態(tài)碼
服務(wù)器向用戶返回的狀態(tài)碼和提示信息凌唬,常見的有以下一些(方括號(hào)中是該狀態(tài)碼對(duì)應(yīng)的HTTP動(dòng)詞),查看全部狀態(tài)碼定義點(diǎn)擊這里。
* 200 OK-[GET]:服務(wù)器成功返回請(qǐng)求數(shù)據(jù),該操作是冪等的客税。
* 201 create -[POST/PUT/PATCH]:用戶新建或者修改數(shù)據(jù)
* 202 Accept - [*]標(biāo)識(shí)一個(gè)請(qǐng)求進(jìn)入后臺(tái)排隊(duì)(異步任務(wù))
* 204 no content - [DELETE]:用戶刪除數(shù)據(jù)成功
* 400 invalid requests- [POST/PUT/PATCH]:用戶發(fā)出的請(qǐng)求錯(cuò)誤况褪,服務(wù)器沒有進(jìn)行新建或者修改的操作,該操作是冪等的更耻。
* 401 Unauthorized- [*]:標(biāo)識(shí)沒有權(quán)限(令牌测垛,用戶名,密碼錯(cuò)誤)秧均。
* 403 Forbidden - [*]: 標(biāo)識(shí)用戶得到授權(quán)(與401錯(cuò)誤相對(duì))食侮,但是訪問是被禁止的。
* 404 not found - [*]: y用戶發(fā)出的請(qǐng)求針對(duì)的是不是存在的記錄目胡,服務(wù)器沒進(jìn)行操作锯七,這個(gè)操作是冪等的。
* 406 Not Acceptable - [GET]:用戶請(qǐng)求格式不可得:(比如用戶請(qǐng)求的是json格式誉己,但是只要xml格式)
* 410 Gone - [GET]:用戶請(qǐng)求資源被永久刪除眉尸,且不會(huì)再得到。
* 422 Unprocesable entity - [POST/PUT/PATCH]當(dāng)創(chuàng)建一個(gè)對(duì)象時(shí)候巨双,發(fā)生一個(gè)驗(yàn)證錯(cuò)誤噪猾。
* 500 internal server error - [*] :服務(wù)器發(fā)生錯(cuò)誤,用戶將無法判斷發(fā)出的請(qǐng)求是否成功筑累。
另外附上GitHub的API設(shè)計(jì),更具參考價(jià)值袱蜡。
6. 各端的具體實(shí)現(xiàn)
如上圖說是,service統(tǒng)一提供了一套R(shí)ESTful API, web+android+ios作為同級(jí)調(diào)用API慢宗,現(xiàn)在都有一些比較成熟的框架來幫助開發(fā)者戒劫。
1. Server
- 推薦: Spring MVC 或者 Jersey 或者 Play Framework
- 教程:Getting Started · Building a RESTful Web Service
2. Android
- 推薦: RetroFit ( Retrofit ) 或者 Volley ( mcxiaoke/android-volley
- 教程:
- Retrofit ??? Getting Started and Create an Android Client
- 快速Android開發(fā)系列網(wǎng)絡(luò)篇之Retrofit
3. iOS
- 推薦:RestKit ( RestKit/RestKit · GitHub )
- 教程:Developing RESTful iOS Apps with RestKit
4. Web
- 可以用重量級(jí)的AngularJS,也可以用輕量級(jí) Backbone + jQuery 等婆廊。
7. Django REST Framework使用
Django REST Framework應(yīng)用會(huì)在下一遍文章中做詳細(xì)分析迅细。
參考資料鏈接:
REST APIs must be hypertext-driven
架構(gòu)風(fēng)格與基于網(wǎng)絡(luò)的軟件架構(gòu)設(shè)計(jì)(Roy Fielding 博士論文中文版)