RESTful Web Service 架構(gòu)剖析

如今微服務(wù)和分布式架構(gòu)變的越來(lái)越流行蹬跃,而簡(jiǎn)單可靠高效维费,跨平臺(tái)跨語(yǔ)言的 Web Service 則是這類(lèi)系統(tǒng)架構(gòu)的基石果元。 RESTful Web Service 恰好滿(mǎn)足這些特點(diǎn),被越來(lái)越多的系統(tǒng)架構(gòu)所采用犀盟。

本文主要面向?qū)?Web Service 有一定理解而晒,需要進(jìn)一步了解基于 REST 形式的 Web Service 的 IT 開(kāi)發(fā)人員和架構(gòu)師。它不是 Web Service 入門(mén)介紹阅畴,你需要較多相關(guān)領(lǐng)域的知識(shí)背景才能理解全部?jī)?nèi)容倡怎。

什么是 RESTful Web Service

作為互聯(lián)網(wǎng)應(yīng)用開(kāi)發(fā)人員,我們經(jīng)常能看到 Web Service贱枣,REST 和 RESTful Web Service 之類(lèi)的描述监署,可我們真的清楚這些概念嗎?

Web Service 簡(jiǎn)單來(lái)說(shuō)是指提供給不同設(shè)備通過(guò)互聯(lián)網(wǎng)(一般使用 HTTP 協(xié)議)進(jìn)行通信和交換數(shù)據(jù)的一種服務(wù)纽哥。RESTful Web Service 是實(shí)現(xiàn) Web Service 的一種方式钠乏。那么到底什么是 RESTful Web Service呢?什么又是 REST 呢春塌?

REST 和 RESTful Web Service

REST (Representational State Transfer) 是由美國(guó)計(jì)算機(jī)科學(xué)家 Roy Fielding在2000年的博士論文提出的一種架構(gòu)方式晓避。Roy Fielding絕對(duì)可以稱(chēng)之為業(yè)界大牛,他現(xiàn)任 Adobe 首席科學(xué)家只壳,是HTTP協(xié)議的首要作者之一俏拱,也是Apache項(xiàng)目的聯(lián)合創(chuàng)始人。

REST 是一種架構(gòu)方式和約定吼句,和具體實(shí)現(xiàn)無(wú)關(guān)锅必,也不一定必須基于Web。我們一般把采用 REST 架構(gòu)的 Web Service 稱(chēng)之 RESTful Web Service惕艳。在實(shí)際項(xiàng)目應(yīng)用中况毅,嚴(yán)格來(lái)說(shuō),我們應(yīng)該稱(chēng)這種 Web Service 為具有 REST 風(fēng)格的 Web Service尔艇。原因是我們?cè)谔幚砗徒鉀Q某些實(shí)際問(wèn)題時(shí)尔许,這種 Service 可能并不完全嚴(yán)格遵守 REST 架構(gòu)的所有必要約定。

RESTful Web Service 和基于SOAP的 Web Services 有著本質(zhì)的不同终娃。使用 SOAP 的 Web Service 實(shí)際上是以協(xié)議(protocol)的形式工作的味廊。因?yàn)?SOAP Web Service 嚴(yán)格規(guī)定了如何發(fā)現(xiàn)和描述 API,其傳輸?shù)南⒁灿袊?yán)格統(tǒng)一的格式(例如傳輸?shù)妮d體XML有嚴(yán)格的格式規(guī)范)棠耕。而 RESTful Web Service 并不是協(xié)議余佛,它沒(méi)有規(guī)定傳輸消息的具體格式,它只是一種約定使用 REST 架構(gòu)實(shí)現(xiàn)的 Web Service窍荧。RESTful Web Service 相比SOAP Web Service 更加簡(jiǎn)單和輕量級(jí)』匝玻現(xiàn)在大部分 RESTful Web Service 都使用類(lèi)似的形式,例如都使用HTTP傳輸蕊退,使用風(fēng)格類(lèi)似的 URL 作為 API 和 使用 JSON 或者 XML 來(lái)傳輸數(shù)據(jù)等等(目前 JSON 占據(jù)主導(dǎo)地位郊楣,并且有持續(xù)流行的趨勢(shì)[1])憔恳。

如果你之前沒(méi)有接觸過(guò)SOAP,你只需記住RESTful Web Service 是一種采用 REST 架構(gòu)約定净蚤,更簡(jiǎn)單钥组,更輕量級(jí)的Web Service

REST 之父大牛 Roy Fielding 在他的論文中,一共從下面6個(gè)方面闡述了 REST 架構(gòu)的約定(REST 應(yīng)該滿(mǎn)足哪些條件今瀑,以及這樣做會(huì)有什么好處)

REST 架構(gòu)約定

  1. CS結(jié)構(gòu)(Client–server)
    客戶(hù)端是一個(gè)相對(duì)獨(dú)立的實(shí)現(xiàn)程梦,它不必考慮數(shù)據(jù)的持久化存儲(chǔ)問(wèn)題。服務(wù)端擁有和保存數(shù)據(jù)橘荠,服務(wù)端不去關(guān)心客戶(hù)端內(nèi)部實(shí)現(xiàn)屿附,也不用關(guān)心客戶(hù)端請(qǐng)求的上下文。服務(wù)端和客戶(hù)端之間遵守相同的接口規(guī)范哥童。在遵守相同接口規(guī)范的前提下拿撩,二者都可以獨(dú)立演化,甚至可以被其它的實(shí)現(xiàn)替代如蚜。

  2. 無(wú)狀態(tài)(Stateless)
    任何時(shí)候一個(gè)客戶(hù)端的請(qǐng)求數(shù)據(jù)都包含能夠讓服務(wù)端完成請(qǐng)求的充分信息压恒,服務(wù)端不依賴(lài)前后不同請(qǐng)求的順序和狀態(tài)信息來(lái)完成請(qǐng)求。請(qǐng)求的session信息由客戶(hù)端持有错邦,并在必要時(shí)連同請(qǐng)求數(shù)據(jù)一起發(fā)送探赫。服務(wù)端可以使用請(qǐng)求中的session信息去其它外部服務(wù)或者數(shù)據(jù)庫(kù)獲取相關(guān)內(nèi)容進(jìn)以便對(duì)該請(qǐng)求做權(quán)限驗(yàn)證等操作。

    如果所需數(shù)據(jù)要通過(guò)多次請(qǐng)求才能完成撬呢,客戶(hù)端必須自己負(fù)責(zé)記錄狀態(tài)(因?yàn)榉?wù)器不跟蹤客戶(hù)端的狀態(tài))伦吠,在下次請(qǐng)求時(shí)附帶發(fā)出。一個(gè)典型的例子是分頁(yè)的實(shí)現(xiàn)魂拦,客戶(hù)端需要自己保存當(dāng)前頁(yè)數(shù)毛仪,請(qǐng)求下一頁(yè)時(shí)作為參數(shù)一起發(fā)給服務(wù)端,服務(wù)端使用該參數(shù)返回正確的下一頁(yè)數(shù)據(jù)芯勘。有些設(shè)計(jì)箱靴,比如Facebook API,服務(wù)端返回?cái)?shù)據(jù)中包含下一頁(yè)數(shù)據(jù)的請(qǐng)求URL荷愕,客戶(hù)端只要記錄這個(gè)URL即可發(fā)起下一頁(yè)的請(qǐng)求衡怀。

    服務(wù)端不依賴(lài)客戶(hù)端的請(qǐng)求順序和狀態(tài)提高了服務(wù)器的可擴(kuò)展性(scalability)。比如在使用Load balancer的情況下安疗,不能因?yàn)槟硞€(gè)請(qǐng)求被分配到其它服務(wù)器而丟失某些信息從而返回不正確的數(shù)據(jù)抛杨。
    無(wú)狀態(tài)的約定也提高了系統(tǒng)的健壯性(reliability)。如果集群服務(wù)器中的其中一臺(tái)發(fā)生故障也不會(huì)對(duì)系統(tǒng)的平穩(wěn)運(yùn)行造成太大影響荐类。

    不過(guò)無(wú)狀態(tài)的約定也是有缺點(diǎn)的怖现,客戶(hù)端必須每次都要帶上相同重復(fù)的信息來(lái)確定自己的身份和狀態(tài),這就造成了傳輸數(shù)據(jù)的冗余性玉罐。然而沒(méi)有一個(gè)架構(gòu)決策是十全十美的屈嗤,最終的決策往往都是相互妥協(xié)的結(jié)果潘拨,我們只能選擇一個(gè)相對(duì)有優(yōu)勢(shì)的決策。

  3. 緩存機(jī)制(Cacheable)
    服務(wù)端應(yīng)該明確規(guī)定返回?cái)?shù)據(jù)的緩存機(jī)制恢共,包括是否可緩存,緩存如何失效以及利用緩存獲取增量數(shù)據(jù)而不必每次獲取全部數(shù)據(jù)等璧亚。合理的緩存設(shè)計(jì)可以減少請(qǐng)求次數(shù)讨韭,進(jìn)而提高服務(wù)器的效率和性能

  4. 系統(tǒng)分層(Layered system)
    客戶(hù)端不用知道數(shù)據(jù)是從服務(wù)端直接返回還是通過(guò)中轉(zhuǎn)代理返回癣蟋。這樣的設(shè)計(jì)也同樣提高了系統(tǒng)的可擴(kuò)展性透硝。比如可以使用負(fù)責(zé)均衡和反向代理等技術(shù)來(lái)對(duì)系統(tǒng)進(jìn)行水平擴(kuò)展和緩存處理,把系統(tǒng)劃分成不同的層次疯搅。使用分層設(shè)計(jì)也方便我們管理不同資源的權(quán)限濒生,有利于提高系統(tǒng)的安全性

  5. 可定制代碼(可選)(Code on demand)
    服務(wù)端可選擇臨時(shí)給客戶(hù)端下發(fā)一些功能代碼讓客戶(hù)端來(lái)執(zhí)行幔欧,從而定制和擴(kuò)展客戶(hù)端的某些功能罪治。比如服務(wù)端可以返回一些 Javascript 代碼讓客戶(hù)端執(zhí)行,去實(shí)現(xiàn)某些特定的功能礁蔗。

  6. 一致的接口(Uniform interface)
    一致的接口對(duì) REST 服務(wù)至關(guān)重要觉义。基于統(tǒng)一的接口規(guī)則可以簡(jiǎn)化系統(tǒng)實(shí)現(xiàn)浴井,降低子系統(tǒng)之間的耦合度晒骇,因?yàn)樽酉到y(tǒng)只要關(guān)注實(shí)現(xiàn)接口即可。在保證接口一致的情況下磺浙,不同的實(shí)現(xiàn)可以各自獨(dú)立演化洪囤。對(duì)于接口的要求有這么四個(gè)方面:

    • 一致的數(shù)據(jù)格式
      雖然服務(wù)端內(nèi)部不同數(shù)據(jù)的存儲(chǔ)格式可能千差萬(wàn)別,但返回給客戶(hù)端的數(shù)據(jù)一定要有一個(gè)統(tǒng)一的表現(xiàn)形式撕氧。比如 Web Service 請(qǐng)求返回格式要么是 HTML瘤缩,要么是 XML,要么是 JSON伦泥,不能返回服務(wù)端自己內(nèi)部使用的特殊格式款咖。

    • 可以對(duì)已有數(shù)據(jù)進(jìn)一步操作(Resource Identifiers)
      如果客戶(hù)端擁有一個(gè)資源,必要時(shí)奄喂,客戶(hù)端應(yīng)該擁有足有的信息去修改和刪除這個(gè)資源铐殃。通常我們只要在返回的數(shù)據(jù)中包含一個(gè) UID 即可做到這點(diǎn)。比如從服務(wù)端獲得了一個(gè)訂單數(shù)據(jù)跨新,這個(gè)訂單數(shù)據(jù)里應(yīng)該保證有一個(gè)唯一的訂單 ID富腊,當(dāng)我們想對(duì)這個(gè)訂單進(jìn)行進(jìn)一步操作時(shí),可以保障操作的是同一個(gè)訂單域帐。

    • 數(shù)據(jù)具有自我描述性
      每項(xiàng)數(shù)據(jù)應(yīng)該是可以自我描述的赘被,方便代碼去處理和解析其中的內(nèi)容是整。比如通過(guò)HTTP返回的數(shù)據(jù)里面有 [MIME type ]信息,我們從MIME type里面可以知道數(shù)據(jù)的具體格式民假,是圖片浮入,視頻還是JSON。

    • 應(yīng)用系統(tǒng)狀態(tài)變化只依賴(lài)超媒體(Hypermedia)

應(yīng)用系統(tǒng)狀態(tài)變化只依賴(lài)于服務(wù)端發(fā)來(lái)的Hypermedia(如超鏈接 hyperlinks)羊异。舉例來(lái)說(shuō)事秀,假設(shè)向一個(gè)微博 Web Service 請(qǐng)求一條微博信息,服務(wù)端響應(yīng)信息中應(yīng)該包含和這條微博相關(guān)的其它的URL野舶∫准#客戶(hù)端可以進(jìn)一步利用這些URL發(fā)起請(qǐng)求來(lái)獲取感興趣的信息。前面章節(jié)中提到的Facebook API 可以從第一頁(yè)的返回?cái)?shù)據(jù)中獲取下一頁(yè)的URL也是基于這個(gè)設(shè)計(jì)理念平道。

REST 的這些約定為我們?cè)O(shè)計(jì) RESTful Web Service 提供了一個(gè)絕佳的范本睹欲。套用這個(gè)范本,在設(shè)計(jì) Web Service 時(shí)一屋,可以在一定程度上避免很多問(wèn)題和少走彎路窘疮。因?yàn)檫@些約定本質(zhì)上都是對(duì)現(xiàn)實(shí)系統(tǒng)設(shè)計(jì)優(yōu)點(diǎn)的一些提煉和總結(jié),它已經(jīng)比較周全的為我們考慮了可能出現(xiàn)的問(wèn)題冀墨,并且提供了解決問(wèn)題的基本原則和方向考余。

本文第三小節(jié)“REST 架構(gòu)約定”的主要內(nèi)容來(lái)自對(duì)參考文檔中的部分內(nèi)容的整理和翻譯。計(jì)算機(jī)科學(xué)有很多非常有價(jià)值的論文轧苫,很多論文是如此的重要以至于能奠定一個(gè)時(shí)代的技術(shù)基礎(chǔ)(比如 Google 的 MapReduce楚堤,可能需自備梯子)。我們只有充分理解了其中的思想和原則才能作出更好的設(shè)計(jì)和架構(gòu)含懊。

下一篇文章我們將結(jié)合HTTP的特性身冬,探討如何設(shè)計(jì) RESTful Web Service API

參考文檔

  1. CH5 - Representational State Transfer (REST)
  2. Representational state transfer

  1. 這個(gè)結(jié)論來(lái)自Goolge Trends(須自備梯子): https://www.google.com/trends/explore?date=all&q=xml%20api,json%20api ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市岔乔,隨后出現(xiàn)的幾起案子酥筝,更是在濱河造成了極大的恐慌,老刑警劉巖雏门,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嘿歌,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡茁影,警方通過(guò)查閱死者的電腦和手機(jī)宙帝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)募闲,“玉大人步脓,你說(shuō)我怎么就攤上這事。” “怎么了靴患?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵仍侥,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么负敏? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮砸紊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘饭宾。我一直安慰自己批糟,他們只是感情好格了,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布看铆。 她就那樣靜靜地躺著,像睡著了一般盛末。 火紅的嫁衣襯著肌膚如雪弹惦。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,155評(píng)論 1 299
  • 那天悄但,我揣著相機(jī)與錄音棠隐,去河邊找鬼。 笑死檐嚣,一個(gè)胖子當(dāng)著我的面吹牛助泽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播嚎京,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼嗡贺,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了鞍帝?” 一聲冷哼從身側(cè)響起诫睬,我...
    開(kāi)封第一講書(shū)人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎帕涌,沒(méi)想到半個(gè)月后摄凡,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蚓曼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年亲澡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纫版。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谷扣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情会涎,我是刑警寧澤裹匙,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站末秃,受9級(jí)特大地震影響概页,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜练慕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一惰匙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧铃将,春花似錦项鬼、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至悯仙,卻和暖如春龄毡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背锡垄。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工沦零, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人货岭。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓路操,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親千贯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子屯仗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)丈牢,斷路器祭钉,智...
    卡卡羅2017閱讀 134,651評(píng)論 18 139
  • 一說(shuō)到REST,我想大家的第一反應(yīng)就是“啊己沛,就是那種前后臺(tái)通信方式慌核。”但是在要求詳細(xì)講述它所提出的各個(gè)約束申尼,以及如...
    時(shí)待吾閱讀 3,423評(píng)論 0 19
  • 渲染引擎 渲染引擎的工作主要是垮卓。。渲染师幕,用來(lái)在屏幕上顯示的內(nèi)容粟按。主流的瀏覽器诬滩,Chrome和Safari用的是開(kāi)源...
    ShawnRong閱讀 323評(píng)論 0 0
  • 收獲 導(dǎo)航ul不要給寬度,給li設(shè)置間距灭将,這樣頁(yè)面在縮小的時(shí)候就可以吧內(nèi)容往里里面收縮 響應(yīng)式頁(yè)面完成疼鸟,目前只兼容...
    毛毛i閱讀 187評(píng)論 0 0
  • 《忘了去懂你》算是一部標(biāo)準(zhǔn)的文藝片,沒(méi)有波瀾起伏的劇情沒(méi)有愛(ài)恨情仇的交織庙曙,敘述方式也是不溫不火的細(xì)膩空镜、冷靜,這對(duì)于...
    娟子的書(shū)房閱讀 308評(píng)論 0 0