天天看點

到底什麼是restful

最近在看web,一直在困擾自己的restful也越來越強烈,在寫這篇部落格的時候其實自己也不是很清楚,那就看看别人是怎麼寫的吧!

越來越多的人開始意識到,網站即軟體,而且是一種新型的軟體。這種”網際網路軟體”采用用戶端/伺服器模式,建立在分布式體系上,通過網際網路通信,具有高延時(high latency)、高并發等特點。網站開發,完全可以采用軟體開發的模式。但是傳統上,軟體和網絡是兩個不同的領域,很少有交集;軟體開發主要針對單機環境,網絡則主要研究系統之間的通信。網際網路的興起,使得這兩個領域開始融合,現在我們必須考慮,如何開發在網際網路環境中使用的軟體。

RESTful架構,就是目前最流行的一種網際網路軟體架構。它結構清晰、符合标準、易于了解、擴充友善,是以正得到越來越多網站的采用。

但是,到底什麼是RESTful架構,并不是一個容易說清楚的問題。下面,我就談談我了解的RESTful架構。

背景

Web(網際網路World Wide Web的簡稱)是個包羅萬象的萬花筒,不同的人從不同的角度觀察,對于Web究竟是什麼會得出大不相同的觀點。作為Web開發者,我們需要從技術上來了解Web。從技術架構層面上看,Web的技術架構包括了四個基石:

URI

HTTP

HyperText(除了HTML外,也可以是帶有超連結的XML或JSON)

MIME

這四個基石互相支撐,促使Web這座宏偉的大廈以幾何級數的速度發展了起來。在這四個基石之上,Web開發技術的發展可以粗略劃分成以下幾個階段:

靜态内容階段:在這個最初的階段,使用Web的主要是一些研究機構。Web由大量的靜态HTML文檔組成,其中大多是一些學術論文。Web伺服器可以被看作是支援超文本的共享檔案伺服器。

CGI程式階段:在這個階段,Web伺服器增加了一些程式設計API。通過這些API編寫的應用程式,可以向用戶端提供一些動态變化的内容。Web伺服器與應用程式之間的通信,通過CGI(Common Gateway Interface)協定完成,應用程式被稱作CGI程式。

腳本語言階段:在這個階段,伺服器端出現了ASP、PHP、JSP、ColdFusion等支援session的腳本語言技術,浏覽器端出現了Java Applet、JavaScript等技術。使用這些技術,可以提供更加豐富的動态内容。

瘦用戶端應用階段:在這個階段,在伺服器端出現了獨立于Web伺服器的應用伺服器。同時出現了Web MVC開發模式,各種Web MVC開發架構逐漸流行,并且占據了統治地位。基于這些架構開發的Web應用,通常都是瘦用戶端應用,因為它們是在伺服器端生成全部的動态内容。

RIA應用階段:在這個階段,出現了多種RIA(Rich Internet Application)技術,大幅改善了Web應用的使用者體驗。應用最為廣泛的RIA技術是DHTML+Ajax。Ajax技術支援在不重新整理頁面的情況下動态更新頁面中的局部内容。同時誕生了大量的Web前端DHTML開發庫,例如Prototype、Dojo、ExtJS、jQuery/jQuery UI等等,很多開發庫都支援單頁面應用(Single Page Application)的開發。其他的RIA技術還有Adobe公司的Flex、微軟公司的Silverlight、Sun公司的JavaFX(現在為Oracle公司所有)等等。

移動Web應用階段:在這個階段,出現了大量面向移動裝置的Web應用開發技術。除了Android、iOS、Windows Phone等作業系統平台原生的開發技術之外,基于HTML5的開發技術也變得非常流行。

從上述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(表述性狀态轉移)的縮寫。

他這樣介紹論文的寫作目的:

“本文研究計算機科學兩大前沿—-軟體和網絡—-的交叉點。長期以來,軟體研究主要關注軟體設計的分類、設計方法的演化,很少客觀地評估不同的設計選擇對系統行為的影響。而相反地,網絡研究主要關注系統之間通信行為的細節、如何改進特定通信機制的表現,常常忽視了一個事實,那就是改變應用程式的互動風格比改變互動協定,對整體表現有更大的影響。我這篇文章的寫作目的,就是想在符合架構原理的前提下,了解和評估以網絡為基礎的應用軟體的架構設計,得到一個功能強、性能好、适宜通信的架構。”

(This dissertation explores a junction on the frontiers of two research disciplines in computer science: software and networking. Software research has long been concerned with the categorization of software designs and the development of design methodologies, but has rarely been able to objectively evaluate the impact of various design choices on system behavior. Networking research, in contrast, is focused on the details of generic communication behavior between systems and improving the performance of particular communication techniques, often ignoring the fact that changing the interaction style of an application can have more impact on performance than the communication protocols used for that interaction. My work is motivated by the desire to understand and evaluate the architectural design of network-based application software through principled use of architectural constraints, thereby obtaining the functional, performance, and social properties desired of an architecture. )

在筆者看來,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的博士論文,就像想要了解孔子的思想應該直接去讀《論語》等著作,而不是首先去讀其他人的轉述一樣。筆者在本文中也僅僅是努力不做一個把經書念錯了的歪嘴和尚而已。那麼,下面我們言歸正傳。

REST詳解

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的五個關鍵詞:

資源(Resource)

資源的表述(Representation)

狀态轉移(State Transfer)

統一接口(Uniform Interface)

超文本驅動(Hypertext Driven)

資源

資源(resource)是一種看待伺服器的方式,即,将伺服器看作是由很多離散的資源組成。每個資源是伺服器上一個可命名的抽象概念。因為資源是一個抽象的概念,是以它不僅僅能代表伺服器檔案系統中的一個檔案、資料庫中的一張表等等具體的東西,可以将資源設計的要多抽象有多抽象,隻要想象力允許而且用戶端應用開發者能夠了解。與面向對象設計類似,資源是以名詞為核心來組織的,首先關注的是名詞。一個資源可以由一個或多個URI來辨別。URI既是資源的名稱,也是資源在Web上的位址。對某個資源感興趣的用戶端應用,可以通過資源的URI與其進行互動。

資源的表述(表現或者展現)

資源的表述是一段對于資源在某個特定時刻的狀态的描述。可以在用戶端-伺服器端之間轉移(交換)。資源的表述可以有多種格式,例如HTML/XML/JSON/純文字/圖檔/視訊/音頻等等。資源的表述格式可以通過協商機制來确定。請求-響應方向的表述通常使用不同的格式。

狀态轉移

狀态轉移(state transfer)與狀态機中的狀态遷移(state transition)的含義是不同的。狀态轉移說的是:在用戶端和伺服器端之間轉移(transfer)代表資源狀态的表述。通過轉移和操作資源的表述,來間接實作操作資源的目的。

統一接口

REST要求,必須通過統一的接口來對資源執行各種操作。對于每個資源隻能執行一組有限的操作。以HTTP/1.1協定為例,HTTP/1.1協定定義了一個操作資源的統一接口,主要包括以下内容:

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的一個關鍵詞,在前面都已經解釋過,就不再贅述了。

從架構風格的抽象高度來看,常見的分布式應用架構風格有三種:

分布式對象(Distributed Objects,簡稱DO)

架構執行個體有CORBA/RMI/EJB/DCOM/.NET Remoting等等

遠端過程調用(Remote Procedure Call,簡稱RPC)

架構執行個體有SOAP/XML-RPC/Hessian/Flash AMF/DWR等等

表述性狀态轉移(Representational State Transfer,簡稱REST)

架構執行個體有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的優勢

比較了三種架構風格之間的差别之後,從面向實用的角度來看,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架構的開發中,已經得到了越來越大的重視。

Roy Thomas Fielding論文下載下傳位址:http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

繼續閱讀