重新認(rèn)識(shí)Rest

微服務(wù)架構(gòu)已經(jīng)很流行饥悴, 從概念上要解決的問題: 認(rèn)識(shí)一個(gè)系統(tǒng)蒿秦,如何將這個(gè)系統(tǒng)劃分(系統(tǒng)的分解)烤镐,識(shí)別出組件, 組件之間如何通訊棍鳖,信息如何交換炮叶,使得協(xié)同完成一件事情。 同樣還要包括渡处,隨著系統(tǒng)的演變镜悉,組件如何演化。

那么組件(模塊或服務(wù))本身的抽象医瘫,以及如何暴露侣肄,如何和外部通訊,如何數(shù)據(jù)交換醇份,以及如何交互稼锅?這些都需要面對(duì)解決的問題, 重讀Roy論文僚纷,重新認(rèn)識(shí)到Rest對(duì)于上面的問題(組件如何暴露矩距,如何通訊,如何交換數(shù)據(jù)怖竭,以及模塊的演化)給出一個(gè)答案锥债。下面談?wù)勛约簩?duì)Rest的理解。

一切皆資源(resource)

Rest是面向資源的架構(gòu)ROA( resource -oriented architecture)痊臭,理解resource這個(gè)概念非常重要哮肚,或者這個(gè)是理解Rest的核心。Rest 是一種理念趣兄,將現(xiàn)實(shí)世界一切抽象為資源绽左,通過資源將現(xiàn)實(shí)世界映射到數(shù)字世界; 就如同面向?qū)ο笸叮瑢F(xiàn)實(shí)世界一切抽象為對(duì)象,通過對(duì)象將現(xiàn)實(shí)世界映射到數(shù)字世界戏蔑。?比如電商里面的一個(gè)商品蹋凝,一個(gè)訂單,一個(gè)快遞單號(hào)总棵,甚至一條評(píng)論都可以抽象為資源鳍寂;更抽象點(diǎn)概念,比如提供在線打印的服務(wù)情龄,每一個(gè)打印的請(qǐng)求也是一個(gè)資源迄汛; 一個(gè)調(diào)度引擎捍壤,每一次調(diào)度的請(qǐng)求都一個(gè)資源。

在資源為基本的抽象單元世界里鞍爱,資源有這么些特性:

1. 每一種現(xiàn)實(shí)客觀事物都可以抽象為資源鹃觉;資源就是現(xiàn)實(shí)世界的抽象的屬性的信息實(shí)體。

2. 每一種資源都有一個(gè)標(biāo)識(shí)睹逃, 或者有多個(gè)標(biāo)識(shí)盗扇, 就是資源的名字;

3. 在給定的上下文沉填,可以通過名字查找到資源本身疗隶;( 資源本身的名字,與物理實(shí)現(xiàn)分離)

4. 計(jì)算是將資源具體化到表現(xiàn)層翼闹;

5. 資源本身具有不可變性斑鼻;

6.? 對(duì)于不同表現(xiàn)層之間的轉(zhuǎn)換時(shí)無損的,之間可以等價(jià)轉(zhuǎn)換猎荠;

7. 計(jì)算結(jié)果也是一種資源卵沉,也有其標(biāo)識(shí)符。

在web世界里面多有一一對(duì)應(yīng)法牲。 #1 是相同的理念史汗;#2 資源標(biāo)識(shí)就是URI ; #3 通過就是DNS查找到資源拒垃; #4 對(duì)應(yīng)動(dòng)態(tài)資源計(jì)算就是一個(gè)請(qǐng)求停撞,通過計(jì)算轉(zhuǎn)換為表現(xiàn)層數(shù)據(jù)給用戶; #5 資源本身邏輯上保持不變悼瓮; #6 不同表現(xiàn)層是等價(jià)的(xml戈毒,json); #7 對(duì)于計(jì)算出來的結(jié)果,也是一種資源横堡;? ?

通過客觀世界映射到數(shù)字世界埋市,那么客觀世界中的互操作,如何體現(xiàn)命贴。下面分別介紹道宅,對(duì)象如何被訪問(URI),對(duì)象如何操作(CRUD)胸蛛,以及信息數(shù)據(jù)如何交換污茵。

URI (統(tǒng)一資源識(shí)別符)

?資源如何被訪問?或者資源如何將資源暴露外部世界葬项? 這個(gè)就是URI泞当,這個(gè)天生就于Web緊密連接在一起的,被用作資源的名字民珍。?

比如對(duì)一個(gè)手機(jī)的描述 http://hostname:80/products/smartphone襟士, 清晰明了這是一個(gè)smarphone的產(chǎn)品盗飒,同時(shí)可以通過URI,找到獲取信息本身陋桂。(URI與URL往往一致)逆趣。這個(gè)是被認(rèn)為理所當(dāng)然或者已經(jīng)熟視無睹,但是理所當(dāng)然的事情都不是這么的簡(jiǎn)單的章喉。 比對(duì)一下汗贫,看看書的URI(ISBN)與URI比較, 看看哪一個(gè)可讀性好一些秸脱?

http://hostname/books/愛麗絲夢(mèng)游仙境

ISBN:7-301-04815-7?

URI是資源的名字落包,就說說名字本身。比如一個(gè)資源

http://host/products/smartphone

http://host/products 也可以理解為名字在網(wǎng)絡(luò)上的namespace摊唇。名字很顯然是一個(gè)名詞性質(zhì)的詞語(yǔ)咐蝇, 試試想想一個(gè)動(dòng)詞的名字是什么感覺:); 同樣名字與其實(shí)現(xiàn)沒有關(guān)系,下面的名字將概念和實(shí)現(xiàn)耦合在一起巷查,不是好的名字有序。

http://host/books/xxx.asp

http://host/books/xxx.php

?同樣名字要名副其實(shí),這個(gè)是程序員程序員的品味和修煉有關(guān)岛请,不在本文范圍里面旭寿,暫且不討論。

統(tǒng)一的方法(CRUD)

Rest 將對(duì)于資源的操作定義為CRUD(get/post/put/delete),是的崇败,是所有的操作盅称!或許這樣說更容易理解一些,相當(dāng)面向?qū)ο罄锩嫠械膶?duì)象的方法后室,當(dāng)且僅當(dāng)只有CRUD操作缩膝。先回顧一下這個(gè)四個(gè)操作的定義,然后再看如何統(tǒng)一所有操作.

get: 對(duì)應(yīng)讀操作岸霹,獲取資源疾层;語(yǔ)義很清晰,只讀應(yīng)該不期望改變資源本身贡避。

post: 創(chuàng)建一個(gè)資源痛黎。 因?yàn)橘Y源ID一般是服務(wù)創(chuàng)建的,服務(wù)器創(chuàng)建成果會(huì)返回新的ID贸桶,這為一個(gè)不等冪操作舅逸。

put:? 更新資源。 這個(gè)需要提交一個(gè)完整的資源皇筛,當(dāng)然包括ID,才能更新坠七。這個(gè)操作經(jīng)常會(huì)和post搞混水醋。 (post就是沒有完整信息比如ID旗笔,就只能由服務(wù)器創(chuàng)建,put是有ID可以提交更新)拄踪。 等冪操作蝇恶。

delete: 刪除資源。 等冪操作惶桐。

冪等操作(idempotentance)撮弧,簡(jiǎn)單理解一個(gè)操作(函數(shù)映射)多次,和映射一次效果一樣姚糊。?

f(f(x)) = f(x)

operation vs status

如何將所有的操作統(tǒng)一到CRUD上呢贿衍? 比如對(duì)于一個(gè)訂單,我們有增刪改查救恨,這個(gè)很好理解與CRUD一一對(duì)應(yīng)贸辈。但是對(duì)于此外的,比如取消肠槽,鎖定一個(gè)訂單如何對(duì)應(yīng)擎淤? 對(duì)于傳統(tǒng)的OO理念我們會(huì)定義一組操作:

class OrderManager{

cancelOrder( int id){...}

?lockOrder(int id) {...}

}

對(duì)于SOAP,RPC我們經(jīng)常都是這么做的秸仙,暴露出方法嘴拢。

對(duì)于Rest里面我們把操作當(dāng)成一個(gè)狀態(tài)的修改。對(duì)于上面的Cancel方法在rest里面可以這樣定義

put? http://host/books/xxx??

body: {? "status": "cancel"}

這樣就將操作轉(zhuǎn)換為狀態(tài)變化寂纪,只要提供狀態(tài)修改的方法席吴,更新操作(put), 就可以統(tǒng)一所有類似的操作弊攘。貌似一個(gè)很簡(jiǎn)單的轉(zhuǎn)化就可以將所有的操作統(tǒng)一抢腐,還是很是強(qiáng)大。

既然CURD可以完全統(tǒng)一所有對(duì)資源的操作襟交,那么很顯然CRUD可以借助于HTTP協(xié)議的動(dòng)詞來實(shí)現(xiàn)迈倍。很是完美,誰(shuí)讓Roy T. Fielding就是http協(xié)議和Rest概念的提出者捣域。

既然通過URI來訪問資源啼染,所有的操作http動(dòng)詞可以來操作。下一個(gè)問題就是信息如何交換焕梅。

Representation(表現(xiàn)層)

數(shù)據(jù)是信息的載迹鹅,而數(shù)據(jù)本身可以有不同表現(xiàn)形式 如xml,json贞言,yaml斜棚,binary。 那么服務(wù)之間如何信息的交換,就是通過表現(xiàn)層來交換弟蚀。先看看傳統(tǒng)的rpc蚤霞,數(shù)據(jù)如何傳輸?數(shù)據(jù)的格式义钉,對(duì)象的本身都在開發(fā)的時(shí)候定義好昧绣。 這樣使得客戶端和服務(wù)器都綁定在一起,沒有辦法單獨(dú)演化升級(jí)捶闸。而對(duì)于Rest定義客戶端和服務(wù)器對(duì)于數(shù)據(jù)可以根據(jù)客戶端的請(qǐng)求來返回(Content -type)夜畴,同樣服務(wù)器端可以支持不同的格式。 同樣之間還可以協(xié)商機(jī)制確定如何傳遞數(shù)據(jù)删壮。 這樣服務(wù)器與客戶端解耦贪绘,可以獨(dú)立升級(jí), 獨(dú)立演化醉锅,是軟件架構(gòu)追求一致追尋的目標(biāo)兔簇。

Stateless (無狀態(tài))

互聯(lián)網(wǎng)上資源天生就可以任何時(shí)間任何地點(diǎn)的可以訪問,其訪問彈性是不受控制的硬耍。如何做到彈性垄琐,這個(gè)一個(gè)挑戰(zhàn). 試試想想一般的程序如果要做到彈性計(jì)算,而不用去改代碼经柴,不是一般挑戰(zhàn)狸窘。 無狀態(tài)很好的適應(yīng)這樣的場(chǎng)景。

在互聯(lián)網(wǎng)上坯认,客戶端瀏覽器發(fā)送URL請(qǐng)求到服務(wù)器翻擒,服務(wù)器接受請(qǐng)求響應(yīng)返回給客戶。 如何客戶訪問量陡增牛哺,比如雙11陋气, 服務(wù)器就通過擴(kuò)展來并發(fā)處理。如果請(qǐng)求是沒有狀態(tài)的引润, 就可以被分發(fā)到不同的服務(wù)器巩趁,服務(wù)器只需要根據(jù)請(qǐng)求的本身去應(yīng)答,而不去考慮請(qǐng)求的上下文淳附。如果有狀態(tài)议慰,那么處理起來就復(fù)雜很多,服務(wù)器需要根據(jù)請(qǐng)求查找上下文奴曙,如果處理的服務(wù)器沒有上下文别凹,就需要同步上下文。更進(jìn)一步洽糟,狀態(tài)更新炉菲,如何保證上下文一致堕战。這些帶來的復(fù)雜度,往往就是bug颁督,影響到開發(fā)效率践啄,提高維護(hù)成本浇雹。 另外沉御,這樣上下文相關(guān)對(duì)于緩存也沒有存在同樣的問題。

當(dāng)然天下沒有免費(fèi)的午餐昭灵。 沒有狀態(tài)就需要對(duì)相應(yīng)每一次客戶端在請(qǐng)求的時(shí)候吠裆,需要額外的信息來標(biāo)識(shí)自己,cookie或者額外的參數(shù)烂完。 很顯然rest不是最優(yōu)的傳輸效率不是最高的试疙。 比起來帶來的可擴(kuò)展性,好處遠(yuǎn)遠(yuǎn)大于那點(diǎn)額外的帶寬占用抠蚣。

HATEOAS

(Hypermedia As The Engine of Application State)

超鏈接就是一個(gè)應(yīng)用程序狀態(tài)引擎祝旷。這個(gè)是Rest對(duì)API的約束, 讓服務(wù)器和客戶端進(jìn)一步交互上解耦嘶窄。這個(gè)和傳統(tǒng)的分布式應(yīng)用交互不太一樣怀跛。 比如rpc,預(yù)先定義一組api柄冲,然后客戶端只能根據(jù)預(yù)先定義的api來與服務(wù)器之間交互吻谋,這樣服務(wù)器和客戶端之間就產(chǎn)生依賴,二者不能獨(dú)自演化现横。

Rest API 對(duì)于每一個(gè)api返回值漓拾,不但需要告訴返回哪些值,同樣還需要告訴下一步有哪些交互戒祠,交互的信息是通過超文本骇两。這樣子從一個(gè)起始點(diǎn)api就可以根據(jù)返回相關(guān)的超鏈接,來進(jìn)行下一步操作姜盈。理想的這樣所有的流程都可以通過一個(gè)api低千,根據(jù)超文本連接完成。貌似爬蟲很喜歡:)

這里有一個(gè)例子

下面是個(gè)例子,首先是一個(gè)GET請(qǐng)求賬戶的信息

? ? GET /account/12345 HTTP/1.1

? ? Host: somebank.org

? ? Accept: application/xml

將會(huì)返回?:


HTTP/1.1 200 OK

Content-Type: application/xml

<account>

<account_number>12345<?/account_number>

<balance currency="usd">100.00 </balance>

<link rel="deposit" / link> <rel="withdraw" / link><rel="transfer" / link>? ? ? ? ? ? ? <rel="close" />

</account>

這樣用戶可以通過返回值中的URL贩据,做下一次操作栋操。 這樣交互不需預(yù)定義API。 碰到的大多數(shù)見到的rest API饱亮,這一點(diǎn)都不滿足矾芙,被稱為restful.

本文回顧一下Rest 理念(一切皆資源),以及rest api的五大原則(URI,Uniform operation近上, representation剔宪,stateless 和?HATEOAS ) 。

https://stackoverflow.com/questions/152871/isnt-resource-oriented-really-object-oriented

https://www.w3.org/People/Connolly/9703-web-apps-essay.html

http://resources.1060research.com/docs/IntroductionToResourceOrientedComputing-1.pdf

https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市葱绒,隨后出現(xiàn)的幾起案子感帅,更是在濱河造成了極大的恐慌,老刑警劉巖地淀,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件失球,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡帮毁,警方通過查閱死者的電腦和手機(jī)实苞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烈疚,“玉大人黔牵,你說我怎么就攤上這事∫危” “怎么了猾浦?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)灯抛。 經(jīng)常有香客問我金赦,道長(zhǎng),這世上最難降的妖魔是什么牧愁? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任素邪,我火速辦了婚禮,結(jié)果婚禮上猪半,老公的妹妹穿的比我還像新娘兔朦。我一直安慰自己,他們只是感情好磨确,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布沽甥。 她就那樣靜靜地躺著,像睡著了一般乏奥。 火紅的嫁衣襯著肌膚如雪摆舟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天邓了,我揣著相機(jī)與錄音恨诱,去河邊找鬼。 笑死骗炉,一個(gè)胖子當(dāng)著我的面吹牛照宝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播句葵,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼厕鹃,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼兢仰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起剂碴,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤把将,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后忆矛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體察蹲,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年洪碳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了递览。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡瞳腌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出镜雨,到底是詐尸還是另有隱情嫂侍,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布荚坞,位于F島的核電站挑宠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏颓影。R本人自食惡果不足惜各淀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望诡挂。 院中可真熱鬧碎浇,春花似錦、人聲如沸璃俗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)城豁。三九已至苟穆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間唱星,已是汗流浹背雳旅。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留间聊,地道東北人攒盈。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像甸饱,于是被迫代替她去往敵國(guó)和親沦童。 傳聞我的和親對(duì)象是個(gè)殘疾皇子仑濒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容