add by zhj start: html
Fielding在批判性繼承前人研究成果的基礎上,創建起來一整套研究和評價軟件架構的方法論。這套方法論的核心是「架構風格」這個概念。架構風格是一種研究和評價軟件架構設計的方法,它是比架構更加抽象的概念。一種架構風格是由一組相互協做的架構約束來定義的。前端
REST架構風格最重要的架構約束有6個:數據庫
通訊只能由客戶端單方面發起,表現爲請求-響應的形式。編程
通訊的會話狀態(Session State)應該所有由客戶端負責維護。瀏覽器
響應內容能夠在通訊鏈的某處被緩存,以改善網絡效率。緩存
通訊鏈的組件之間經過統一的接口相互通訊,以提升交互的可見性。爲了使用統一接口,REST又使用了一些約束:面向資源,資源有標識符URI,資源表述,一組受限且定義良好的資源操做等。安全
(1)面向資源的。從資源的角度思考,Web常常被稱做是「面向資源的」,資源能夠是抽象的;性能優化
(2)資源標識符。要使用一個資源,咱們須要可以在網絡上標識它,這就是URI,Uniform Resource Identifier統一資源標識符。URI在HTTP中對應於URL,資源與資源標識符是一對多關係服務器
(3)資源表述。即資源的表現方式,也稱爲資源視圖,如XML, JSON, HTML, MP3, JPEG等,資源與其表述是一對多關係。在HTTP中經過HTTP header Accept, Content-Type指定restful
(4)資源的操做方法。uniform interface,統一接口包含一組受限的定義良好的操做,由它們進行資源的訪問和操做,統一接口獨立於資源的URI。在HTTP協議中即爲GET/PUT/POST等method,
這些動詞都有必定的含義,不該該亂用,具體定義見RESTful HTTP的實踐。另外還包括HTTP定義的響應狀態集合,如200 OK, 201 Created等,客戶端經過HTTP method,對服務器端資源進行操做,實現"表現層狀態轉化"。
REST(Representational State Transfer,表述性狀態轉移)是指:相互連接的資源經過交換表明資源狀態的表述來進行通訊。超連接說白了就是URI--統一資源標識符
經過限制組件的行爲(即,每一個組件只能「看到」與其交互的緊鄰層),將架構分解爲若干等級的層。
支持經過下載並執行一些代碼(例如Java Applet、Flash或JavaScript),對客戶端的功能進行擴展。
最後說一下HTTP,及HTTP與REST的關係。HTTP即HyperText Transfer Protocol,翻譯成「超文本轉移協議」更準確。REST是用來指導HTTP/1.1協議設計的理論框架(也稱爲架構風格),後來Roy Fielding對這套理論框架進行了更爲系統、嚴謹地闡述。
對於使用HTTP的人員來講,統一接口應該是咱們理解和實踐REST的關鍵,其它約束其實沒必要太關心
add by zhj end
本文是「深刻探索REST」專欄系列深度內容中的第二篇,它將帶您領略REST架構的起源、與Web的關係、REST架構的本質及特性,以及REST架構與其餘架構風格之間的比較。
在移動互聯網、雲計算迅猛發展的今天,做爲一名Web開發者,若是您還沒據說過「REST」這個buzzword,顯然已經落伍了。誇張點說,甚至「出了門都很差意思跟別人打招呼」。儘管如此,對於REST這個泊來品的理解,大多數人(包括一些資深的架構師)仍然停留在「盲人摸象」的階段。經常聽到各類各樣關於REST的說法,例如:有人說:「咱們這套新的API決定不用Web Service(SOAP+WSDL),而是直接使用HTTP+JSON,也就是用RESTful的方式來開發。」 不用SOAP,甚至也不用XML,就自動變成了RESTful了。還有人認爲:REST與傳統的Web Service其實沒有本質區別,只是對於URI的構造方式提出了更多要求,而這些要求Web Service徹底均可以實現。潛臺詞是:既生瑜,何生亮。Web Service已經足夠好了,幹嗎還要再折騰什麼REST。這些對於REST的不一樣說法,果然如此嗎?REST到底是什麼?是一種新的技術、一種新的架構、仍是一種新的規範?
對於這些問題筆者先不解答,爲了深刻理解REST是什麼,咱們須要回顧一下Web發展的最初年代,從源頭上講講REST是怎麼得來的。
Web(萬維網World Wide Web的簡稱)是個一應俱全的萬花筒,不一樣的人從不一樣的角度觀察,對於Web到底是什麼會得出大不相同的觀點。做爲Web開發者,咱們須要從技術上來理解Web。從技術架構層面上看,Web的技術架構包括了四個基石:
這四個基石相互支撐,促使Web這座宏偉的大廈以幾何級數的速度發展了起來。在這四個基石之上,Web開發技術的發展能夠粗略劃分紅如下幾個階段:
從上述Web開發技術的發展過程看,Web從最初其設計者所構思的主要支持靜態文檔的階段,逐漸變得愈來愈動態化。Web應用的交互模式,變得愈來愈複雜:從靜態文檔發展到之內容爲主的門戶網站、電子商務網站、搜索引擎、社交網站,再到以娛樂爲主的大型多人在線遊戲、手機遊戲。
在互聯網行業,實踐老是走在理論的前面。Web發展到了1995年,在CGI、ASP等技術出現以後,沿用了多年、主要面向靜態文檔的HTTP/1.0協議已經沒法知足Web應用的開發需求,所以須要設計新版本的HTTP協議。在HTTP/1.0協議專家組之中,有一位年輕人脫穎而出,顯示出了不凡的洞察力,後來他成爲了HTTP/1.1協議專家組的負責人。這位年輕人就是Apache HTTP服務器的核心開發者Roy Fielding,他仍是Apache軟件基金會的合做創始人。
Roy Fielding和他的同事們在HTTP/1.1協議的設計工做中,對於Web之因此取得巨大成功,在技術架構方面的因素作了一番深刻的總結。Fielding將這些總結歸入到了一套理論框架之中,而後使用這套理論框架中的指導原則,來指導HTTP/1.1協議的設計方向。HTTP/1.1協議的第一個草稿是在1996年1月發佈的,通過了三年多時間的修訂,於1999年6月成爲了IETF的正式規範(包括了RFC 2616以及用於對客戶端作身份認證的RFC 2617)。HTTP/1.1協議設計的極爲成功,以致於發佈以後整整10年時間裏,都沒有多少人認爲有修訂的必要。用來指導HTTP/1.1協議設計的這套理論框架,最初是以備忘錄的形式在專家組成員之間交流,除了IETF/W3C的專家圈子,並無在外界普遍流傳。Fielding在完成HTTP/1.1協議的設計工做以後,回到了加州大學歐文分校繼續攻讀本身的博士學位。第二年(2000年)在他的博士學位論文Architectural Styles and the Design of Network-based Software Architectures中,Fielding更爲系統、嚴謹地闡述了這套理論框架,而且使用這套理論框架推導出了一種新的架構風格,而且爲這種架構風格取了一個使人輕鬆愉快的名字「REST」——Representational State Transfer(表述性狀態轉移)的縮寫。
在筆者看來,Fielding這篇博士論文在Web發展史上的價值,不亞於Web之父Tim Berners-Lee關於超文本的那篇經典論文。然而遺憾的是,這篇博士論文在誕生以後的將近5年時間裏,一直沒有獲得足夠的重視。例如Web Service相關規範SOAP/WSDL的設計者們,顯然不大理解REST是什麼,HTTP/1.1到底是一個什麼樣的協議、爲什麼要設計成這個樣子。
這種狀況在2005年以後有了很大的改善,隨着Ajax、Ruby on Rails等新的Web開發技術的興起,在Web開發技術社區掀起了一場重歸Web架構設計本源的運動,REST架構風格獲得了愈來愈多的關注。在2007年1月,支持REST開發的Ruby on Rails 1.2版正式發佈,而且將支持REST開發做爲Rails將來發展中的優先內容。Ruby on Rails的創始人DHH作了一個名爲「World of Resources」的精彩演講,DHH在Web開發技術社區中的強大影響力,使得REST一會兒處在Web開發技術舞臺的聚光燈之下。
今天,各類流行的Web開發框架,幾乎沒有不支持REST開發的了。大多數Web開發者都是經過閱讀某種REST開發框架的文檔,以及經過一些例子代碼來學習REST開發的。然而,經過例子代碼來學習REST有很是大的侷限性。由於REST並非一種具體的技術,也不是一種具體的規範,REST實際上是一種內涵很是豐富的架構風格。經過例子代碼來學習REST,除了學習到一種有趣的Web開發技術以外,並不能全面深刻的理解REST到底是什麼。甚至還會誤覺得這些簡單的例子代碼就是REST自己,REST不過是一種簡單的Web開發技術而已。就像盲人摸象同樣,有的人摸到了象鼻子、有的人摸到了象耳朵、有的人摸到了象腿、有的人摸到了象尾巴。他們都堅信本身感受到的大象,纔是最真實的大象,而其餘人的感受都是錯誤的。
對於不理解REST的Web開發者,人們習慣於展現一些例子代碼來讓他們理解REST,筆者不贊同上述作法。若是Web開發者想要深刻理解REST是什麼,就很難避開Fielding的這篇博士論文。筆者在本文中對於REST是什麼的介紹,也是基於Fielding的博士論文的。儘管如此,筆者強烈建議本文的讀者親自去通讀一下Fielding的博士論文,就像想要了解孔子的思想應該直接去讀《論語》等著做,而不是首先去讀其餘人的轉述同樣。筆者在本文中也僅僅是努力不作一個把經書唸錯了的歪嘴和尚而已。那麼,下面咱們言歸正傳。
在Fielding的這篇名爲Architectural Styles and the Design of Network-based Software Architectures的博士論文(中文版名爲《架構風格與基於網絡的軟件架構設計》)中,提出了一整套基於網絡的軟件(即所謂的「分佈式應用」)的設計方法,值得全部分佈式應用的開發者仔細閱讀、深刻體會。
在論文的前三章中,Fielding在批判性繼承前人研究成果的基礎上,創建起來一整套研究和評價軟件架構的方法論。這套方法論的核心是「架構風格」這個概念。架構風格是一種研究和評價軟件架構設計的方法,它是比架構更加抽象的概念。一種架構風格是由一組相互協做的架構約束來定義的。架構約束是指軟件的運行環境施加在架構設計之上的約束。
在論文的第四章中,Fielding研究了Web這樣一個分佈式系統對於軟件架構設計提出了哪些需求。在第五章中,Fielding將第四章Web提出的需求具體化爲一些架構約束,經過逐步添加各類架構約束,推導出來了REST這種新的架構風格。
REST架構風格的推導過程以下圖所示:
圖1:REST所繼承的架構風格約束(原圖可在這裏下載)
在圖1中,每個橢圓形裏面的縮寫詞表明瞭一種架構風格,而每個箭頭邊的單詞表明瞭一種架構約束。
REST架構風格最重要的架構約束有6個:
通訊只能由客戶端單方面發起,表現爲請求-響應的形式。
通訊的會話狀態(Session State)應該所有由客戶端負責維護。
響應內容能夠在通訊鏈的某處被緩存,以改善網絡效率。
通訊鏈的組件之間經過統一的接口相互通訊,以提升交互的可見性。
經過限制組件的行爲(即,每一個組件只能「看到」與其交互的緊鄰層),將架構分解爲若干等級的層。
支持經過下載並執行一些代碼(例如Java Applet、Flash或JavaScript),對客戶端的功能進行擴展。
在論文中推導出的REST架構風格以下圖所示:
圖2:REST架構風格(原圖可在這裏下載)
而HTTP/1.1協議做爲一種REST架構風格的架構實例,其架構以下圖所示:
圖3:一個基於REST的架構的過程視圖(原圖可在這裏下載)
用戶代理處在三個並行交互(a、b和c)的中間。用戶代理的客戶端鏈接器緩存沒法知足請求,所以它根據每一個資源標識符的屬性和客戶端鏈接器的配置,將每一個請求路由到資源的來源。請求(a)被髮送到一個本地代理,代理隨後訪問一個經過DNS查找發現的緩存網關,該網關將這個請求轉發到一個可以知足該請求的來源服務器,服務器的內部資源由一個封裝過的對象請求代理(object request broker)架構來定義。請求(b)直接發送到一個來源服務器,它可以經過本身的緩存來知足這個請求。請求(c)被髮送到一個代理,它可以直接訪問WAIS(一種與Web架構分離的信息服務),並將WAIS的響應翻譯爲一種通用的鏈接器接口可以識別的格式。每個組件只知道與它們本身的客戶端或服務器鏈接器的交互;整個過程拓撲是咱們的視圖的產物。
經過比較圖2和圖3,讀者不難發現這兩張圖中的架構是高度一致的。對於HTTP/1.1協議爲什麼要設計成這個樣子,讀者想必已經有所領悟。
在論文的第六章中,Fielding對於到2000年爲止在Web基礎架構協議的設計和開發方面的一些經驗教訓進行了深刻的分析。其中,「HTTP不是RPC」、「HTTP不是一種傳輸協議」兩部分值得讀者反覆閱讀。時至13年以後的今日,對於HTTP協議的誤解仍然普遍存在。
以上簡要介紹了Fielding博士論文中的內容。爲了幫助讀者仔細閱讀Fielding的博士論文,筆者整理了一套Fielding博士論文的導讀,將在本專欄後續文章中載出。
REST到底是什麼?由於REST的內涵很是豐富,因此很難用一兩句話解釋清楚這個問題。
首先,REST是Web自身的架構風格。REST也是Web之因此取得成功的技術架構方面因素的總結。REST是世界上最成功的分佈式應用架構風格(成功案例:Web,還不夠嗎?)。它是爲 運行在互聯網環境 的 分佈式 超媒體系統量身定製的。互聯網環境與企業內網環境有很是大的差異,最主要的差異是兩個方面:
可伸縮性需求沒法控制:併發訪問量可能會暴漲,也可能會暴跌。
安全性需求沒法控制:沒法控制客戶端發來的請求的格式,極可能會是惡意的請求。
而所謂的「超媒體系統」,即,使用了超文本的系統。能夠把「超媒體」理解爲超文本+媒體內容。
REST是HTTP/1.1協議等Web規範的設計指導原則,HTTP/1.1協議正是爲實現REST風格的架構而設計的。新的Web規範,其設計必須符合REST的要求,不然整個Web的體系架構會由於引入嚴重矛盾而崩潰。這句話不是危言聳聽,作個類比,假如蘇州市政府贊成在市區著名園林的附近大型土木,建造大量具備後現代風格的摩天大樓,那麼不久以後世界聞名的蘇州園林美景將不復存在。
上述這些關於「REST是什麼」的描述,能夠總結爲一句話:REST是全部Web應用都應該遵照的架構設計指導原則。固然,REST並非法律,違反了REST的指導原則,仍然可以實現應用的功能。可是違反了REST的指導原則,會付出不少代價,特別是對於大流量的網站而言。
要深刻理解REST,須要理解REST的五個關鍵詞:
什麼是資源?
資源是一種看待服務器的方式,即,將服務器看做是由不少離散的資源組成。每一個資源是服務器上一個可命名的抽象概念。由於資源是一個抽象的概念,因此它不只僅能表明服務器文件系統中的一個文件、數據庫中的一張表等等具體的東西,能夠將資源設計的要多抽象有多抽象,只要想象力容許並且客戶端應用開發者可以理解。與面向對象設計相似,資源是以名詞爲核心來組織的,首先關注的是名詞。一個資源能夠由一個或多個URI來標識。URI既是資源的名稱,也是資源在Web上的地址。對某個資源感興趣的客戶端應用,能夠經過資源的URI與其進行交互。
什麼是資源的表述?
資源的表述是一段對於資源在某個特定時刻的狀態的描述。能夠在客戶端-服務器端之間轉移(交換)。資源的表述能夠有多種格式,例如HTML/XML/JSON/純文本/圖片/視頻/音頻等等。資源的表述格式能夠經過協商機制來肯定。請求-響應方向的表述一般使用不一樣的格式。
什麼是狀態轉移?
狀態轉移(state transfer)與狀態機中的狀態遷移(state transition)的含義是不一樣的。狀態轉移說的是:在客戶端和服務器端之間轉移(transfer)表明資源狀態的表述。經過轉移和操做資源的表述,來間接實現操做資源的目的。
什麼是統一接口?
REST要求,必須經過統一的接口來對資源執行各類操做。對於每一個資源只能執行一組有限的操做。以HTTP/1.1協議爲例,HTTP/1.1協議定義了一個操做資源的統一接口,主要包括如下內容:
7個HTTP方法:GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS
HTTP頭信息(可自定義)
HTTP響應狀態代碼(可自定義)
一套標準的內容協商機制
一套標準的緩存機制
一套標準的客戶端身份認證機制
REST還要求,對於資源執行的操做,其操做語義必須由HTTP消息體以前的部分徹底表達,不能將操做語義封裝在HTTP消息體內部。這樣作是爲了提升交互的可見性,以便於通訊鏈的中間組件實現緩存、安全審計等等功能。
什麼是超文本驅動?
「超文本驅動」又名「將超媒體做爲應用狀態的引擎」(Hypermedia As The Engine Of Application State,來自Fielding博士論文中的一句話,縮寫爲HATEOAS)。將Web應用看做是一個由不少狀態(應用狀態)組成的有限狀態機。資源之間經過超連接相互關聯,超連接既表明資源之間的關係,也表明可執行的狀態遷移。在超媒體之中不只僅包含數據,還包含了狀態遷移的語義。以超媒體做爲引擎,驅動Web應用的狀態遷移。經過超媒體暴露出服務器所提供的資源,服務器提供了哪些資源是在運行時經過解析超媒體發現的,而不是事先定義的。從面向服務的角度看,超媒體定義了服務器所提供服務的協議。客戶端應該依賴的是超媒體的狀態遷移語義,而不該該對因而否存在某個URI或URI的某種特殊構造方式做出假設。一切都有可能變化,只有超媒體的狀態遷移語義可以長期保持穩定。
一旦讀者理解了上述REST的五個關鍵詞,就很容易理解REST風格的架構所具備的6個的主要特徵:
面向資源(Resource Oriented)
可尋址(Addressability)
連通性(Connectedness)
無狀態(Statelessness)
統一接口(Uniform Interface)
超文本驅動(Hypertext Driven)
這6個特徵是REST架構設計優秀程度的判斷標準。其中,面向資源是REST最明顯的特徵,即,REST架構設計是以資源抽象爲核心展開的。可尋址說的是:每個資源在Web之上都有本身的地址。連通性說的是:應該儘可能避免設計孤立的資源,除了設計資源自己,還須要設計資源之間的關聯關係,而且經過超連接將資源關聯起來。無狀態、統一接口是REST的兩種架構約束,超文本驅動是REST的一個關鍵詞,在前面都已經解釋過,就再也不贅述了。
從架構風格的抽象高度來看,常見的分佈式應用架構風格有三種:
架構實例有CORBA/RMI/EJB/DCOM/.NET Remoting等等
架構實例有SOAP/XML-RPC/Hessian/Flash AMF/DWR等等
架構實例有HTTP/WebDAV
DO和RPC這兩種架構風格在企業應用中很是廣泛,而REST則是Web應用的架構風格,它們之間有很是大的差異。
REST與DO的差異在於:
REST支持抽象(即建模)的工具是資源,DO支持抽象的工具是對象。在不一樣的編程語言中,對象的定義有很大差異,因此DO風格的架構一般都是與某種編程語言綁定的。跨語言交互即便能實現,實現起來也會很是複雜。而REST中的資源,則徹底中立於開發平臺和編程語言,可使用任何編程語言來實現。
DO中沒有統一接口的概念。不一樣的API,接口設計風格能夠徹底不一樣。DO也不支持操做語義對於中間組件的可見性。
DO中沒有使用超文本,響應的內容中只包含對象自己。REST使用了超文本,能夠實現更大粒度的交互,交互的效率比DO更高。
REST支持數據流和管道,DO不支持數據流和管道。
DO風格一般會帶來客戶端與服務器端的緊耦合。在三種架構風格之中,DO風格的耦合度是最大的,而REST的風格耦合度是最小的。REST鬆耦合的源泉來自於統一接口+超文本驅動。
REST與RPC的差異在於:
REST支持抽象的工具是資源,RPC支持抽象的工具是過程。REST風格的架構建模是以名詞爲核心的,RPC風格的架構建模是以動詞爲核心的。簡單類比一下,REST是面向對象編程,RPC則是面向過程編程。
RPC中沒有統一接口的概念。不一樣的API,接口設計風格能夠徹底不一樣。RPC也不支持操做語義對於中間組件的可見性。
RPC中沒有使用超文本,響應的內容中只包含消息自己。REST使用了超文本,能夠實現更大粒度的交互,交互的效率比RPC更高。
REST支持數據流和管道,RPC不支持數據流和管道。
由於使用了平臺中立的消息,RPC風格的耦合度比DO風格要小一些,可是RPC風格也經常會帶來客戶端與服務器端的緊耦合。支持統一接口+超文本驅動的REST風格,能夠達到最小的耦合度。
比較了三種架構風格之間的差異以後,從面向實用的角度來看,REST架構風格能夠爲Web開發者帶來三方面的利益:
採用REST架構風格,對於開發、測試、運維人員來講,都會更簡單。能夠充分利用大量HTTP服務器端和客戶端開發庫、Web功能測試/性能測試工具、HTTP緩存、HTTP代理服務器、防火牆。這些開發庫和基礎設施早已成爲了平常用品,不須要什麼火箭科技(例如神奇昂貴的應用服務器、中間件)就能解決大多數可伸縮性方面的問題。
充分利用好通訊鏈各個位置的HTTP緩存組件,能夠帶來更好的可伸縮性。其實不少時候,在Web前端作性能優化,產生的效果不亞於僅僅在服務器端作性能優化,可是HTTP協議層面的緩存經常被一些資深的架構師徹底忽略掉。
統一接口+超文本驅動,帶來了最大限度的鬆耦合。容許服務器端和客戶端程序在很大範圍內,相對獨立地進化。對於設計面向企業內網的API來講,鬆耦合並非一個很重要的設計關注點。可是對於設計面向互聯網的API來講,鬆耦合變成了一個必選項,不只在設計時應該關注,並且應該放在最優先位置。
有的讀者可能會問:「你說了這麼多,REST難道就沒有任何缺點了嗎?」固然不是,正如Fielding在博士論文中闡述的那樣,評價一種軟件架構的優劣,不能脫離開軟件的具體運行環境。永遠不存在適用於任何運行環境的、包治百病的銀彈式架構。筆者在前面強調過REST是一種爲運行在互聯網環境中的Web應用量身定製的架構風格。REST在互聯網這個運行環境之中已經佔據了統治地位,然而,在企業內網運行環境之中,REST還會面臨DO、RPC的巨大挑戰。特別是一些對實時性要求很高的應用,REST的表現不如DO和RPC。因此須要針對具體的運行環境來具體問題具體分析。可是,REST能夠帶來的上述三方面的利益即便在開發企業應用時,仍然是很是有價值的。因此REST在企業應用開發,特別是在SOA架構的開發中,已經獲得了愈來愈大的重視。本專欄將有一篇文章專門介紹REST在企業級應用中與SOA的結合。
到了這裏,「REST到底是什麼」這個問題筆者就解答完了。本文開頭那些說法是否正確,筆者仍是笑而不語,讀者此時應該已經有了本身的判斷。在接下來的REST系列文章中,我將會爲讀者澄清一些關於HTTP協議和REST的常見誤解。
參考資料:
感謝馬國耀對本文的策劃和審校。