国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Ajax 和 REST,第 1 部分

在短短 15 年中,World Wide Web 已經從一項研究實驗成長為現代社會的技術支柱。最初發(fā)明 Web 的目的是使人們可以輕松發(fā)布和鏈接信息,現在它已經發(fā)展為軟件應用程序的可行平臺。但隨著應用程序通過使用富應用程序模型和生成個性化內容而獲得了更多的融入性,它們的架構對 Web 架構風格 REST(Representational State Transfer)的違背也越來越多。這種違背會降低應用程序的可伸縮性,增加系統(tǒng)復雜性。

新興的 Ajax Web 客戶機架構風格讓融入式 Web 應用程序與 REST 架構風格協調一致。使它們可以盡享 REST 那些出色的特性,同時又消除了應用程序違背 REST 準則時帶來的不良特性。本文將介紹為融入式 Web 應用程序成功結合 Ajax 和 REST 的方法與原因。

請訪問 Ajax 技術資源中心,這是有關 Ajax 編程模型信息的一站式中心,包括很多文檔、教程、論壇、blog、wiki 和新聞。任何新信息都能在這里找到。

REST:Web 架構

盡管 World Wide Web 是在數十年的相關研究基礎上建立起來的,但它的有效誕生日期是 1990 年 12 月,當時 Tim Berners-Lee 完成了 Web 主要組件的工作原型:統(tǒng)一資源標識符(URI)、HTTP、HTML、瀏覽器和服務器。Web 被迅猛采用,遠遠超過了先驅者們的預期。在 Roy Fielding 最出名的系列文章中(請參看 參考資料),他描述了自己當時的心情:

“盡管對其成功感到興奮不已,但是 Internet 開發(fā)者社區(qū)逐漸開始擔心,Web 使用的這種快速增長,以及早期 HTTP 的一些拙劣的網絡特性,會快速壓倒 Internet 基礎設施所能承擔的容量,從而導致突然的崩塌。”

“一種架構在設計時就應該考慮到一組特性,讓它可以滿足甚至超越系統(tǒng)的需求。忽略這些特性可能會導致后期變更干擾整個架構,就像是使用一扇落地窗去取代承重墻會破壞整個建筑結構的可靠性。” —— Roy Fielding

Fielding 和其他人對 Web 架構及其是否能夠足以支持各種擴展和用法重新進行了審視。這種重新審視的有形結果包括更新諸如 URI 和 HTTP 之類的一些重要標準。這種重新審視還獲得了一些無形但卻非常有意義的結果:為超級媒體應用程序確定了一種新的架構風格,Fielding 將其命名為 REST(Representational State Transfer)。Fielding 斷言,使用且符合 REST 設計約束的 Web 上部署的組件可以充分利用 Web 的有用特性。他還警告說,違背 REST 準則的 Web 組件都將無法利用這些優(yōu)點。

早期時,大部分 Web 站點和簡單的 Web 應用程序實際上都是遵守 REST 準則的。但是隨著融入式 Web 應用程序的日益普及,Web 應用程序架構逐漸開始背離 REST 準則了,此后因果循環(huán),情況日益惡化。融入式服務器端 Web 架構的問題很難分析清楚,因為在使用這種架構風格的十年中,已經建立起這樣一種信仰:這些問題都是 Web 應用程序架構所固有的。實際上,這并非是 Web 應用程序架構的問題。而是由服務器端 Web 應用程序架構風格所產生的問題。要打破這種偏見,我們來回顧一下整個架構是如何發(fā)展到現在這種狀態(tài)的,這會很有幫助。我們將說明為什么在 Ajax 應用程序創(chuàng)建在商業(yè)上可行之后,過去接受的很多假設現在都不再成立了。





回頁首


Web 應用程序的簡史

Berners-Lee 創(chuàng)造了 Web,最初是將 Web 作為研究人員遠程共享文檔和在文檔之間創(chuàng)建簡單鏈接以加速知識和思想傳播的一種手段。然而,URI 標準的架構特征很快實現了除靜態(tài)文件之外更多內容的共享。

提供靜態(tài)文檔的 Web 站點

Web 上最早的內容由一些靜態(tài) HTML 文檔組成,其中有很多到其他靜態(tài)文檔的鏈接,如圖 1 所示:


圖 1. 提供靜態(tài)文檔的 Web 站點

REST 使靜態(tài)文檔的檢索極其高效、可伸縮,這是因為它們可以根據 URI 和最后修改日期來輕松緩存。很快開發(fā)人員就超越了靜態(tài)文檔的領域,開始動態(tài)文檔的提供。

早期的動態(tài) Web 應用程序

Berners-Lee 和其他人設計了 URI 標準,為資源的統(tǒng)一唯一標識提供支持,同時使其表示(HTML、文本等)根據 Web 客戶機(通常是 Web 瀏覽器)和 Web 服務器之間的協商結果而變化。由于 URI 將資源標識和資源的底層存儲機制區(qū)分開來,因此 Web 開發(fā)人員可以創(chuàng)建一些程序,使之檢查 URI 語法,并動態(tài)生成文檔,將預先定義的 UI 元素和動態(tài)檢索的數據(通常是從關系數據庫中)合并在一起,如圖 2 所示。盡管這些文檔是生成的,但是它們的緩存特征與靜態(tài)文件的完全相同。


圖 2. 以嵌入 HTML 模板代碼形式提供數據庫記錄的 Web 站點

此類早期應用程序的一個簡單例子是統(tǒng)一目錄 Web 應用程序。這種應用程序通常以如下方式工作:

  1. 用戶在 Web 表單中輸入名字(例如,Bill Higgins),并單擊提交按鈕。
  2. 表單根據輸入的名字創(chuàng)建一個 URI,并從服務器上請求這個 URI 的內容(例如 GET http://psu.edu/Directory/Bill+Higgins)。
  3. 服務器檢查這個 URI,并使用這個學生的電話號碼和地址來生成一個 Web 頁面。
  4. 服務器將所生成的頁面發(fā)回到用戶的瀏覽器上。

這種交互的一個重要特性是它是冪等的(idempotent),也就是說除非底層資源發(fā)生變化(例如 Bill 修改了自己的電話號碼),否則同一請求的結果總是相同的。這意味著瀏覽器或代理服務器都可以在本地對 Bill Higgins 的文檔進行緩存,只要底層資源沒有發(fā)生變化,那就可以從本地緩存中檢索資源,而不再需要從遠程服務器檢索。這種方法能提高用戶感受到的響應性,并增加系統(tǒng)整體效率和可伸縮性。這些早期的動態(tài) Web 應用程序可以很好地工作,將大量的信息送至用戶指尖。

融入式 Web 應用程序

下一代 Web 應用程序的目標就是高度融入,提供個性化的內容和富應用程序模型。在過去十年中,Web 開發(fā)人員成功創(chuàng)建了這些融入式應用程序。一個非常恰當的例子是 Amazon.com 電子商務站點。當用戶與 Amazon Web 應用程序進行交互時,它會創(chuàng)建復雜的客戶頁面來推薦有針對性的商品,顯示瀏覽歷史記錄,并顯示用戶購物車中商品的價格。





回頁首


融入式服務器端應用程序和 REST

融入式 Web 應用程序確實非常有用,但服務器端的融入式 Web 應用程序風格從根本上來說是不符合 REST 架構準則的。具體來說,它違背了一項關鍵的 REST 約束,并且沒有利用 REST 最為重要的一些優(yōu)點,因此又產生了一組新問題。

違背了 “無狀態(tài)服務器” 約束

REST 的 “客戶機-無狀態(tài)-服務器” 約束禁止在服務器上保存會話狀態(tài)。符合這一約束進行設計可以提高系統(tǒng)的可見性、可靠性和可伸縮性。但是融入式服務器端 Web 應用程序希望能夠為單個用戶提供大量個性化內容,因此必須在兩種設計之間作出選擇。第一種設計要在每個客戶機請求中都發(fā)送大量狀態(tài)信息,因此每個請求都完整地保留了上下文的內容,服務器是無狀態(tài)的。第二種解決方案表面上來看比較簡單,應用程序開發(fā)人員和中間件供應商都比較傾向于這種方法,它只是簡單地發(fā)送一個用戶標識,并在服務器端為這個標識關聯一個 “用戶會話”(如圖 3 所示)。第二種設計直接違背了客戶機-無狀態(tài)-服務器約束。盡管它確實可以實現我們想要的用戶功能(具體來說就是指個性化),但卻對這個架構進行了極大的改動。


圖 3. 融入式服務器端 Web 應用程序,其中包含了大量服務器端會話狀態(tài)

Java™ Servlet 的 HttpSession API 正是一個此類變動的例子。HttpSession 讓我們可以在狀態(tài)和特定用戶之間建立關聯。這個 API 看起來對于開發(fā)新手非常簡單。實際上,它似乎可以將任何對象保存到 HttpSession 中,并且不需要自己實現任何特定的查找邏輯就可以將這些對象取出來。但是當我們開始在 HttpSession 中放入更多對象時,就會開始注意到我們的應用服務器要占用的內存和處理資源越來越多。很快我們就確定自己需要將應用程序部署到集群環(huán)境中來應對日益增加的資源需求。然后就會認識到,要讓 HttpSession 在集群環(huán)境中工作,每個對象都必須實現 Java 的 Serializable 接口,以使會話數據能夠在集群環(huán)境中的服務器間傳遞。然后必須確定應用服務器在關機/重啟過程中是否要繼續(xù)維護會話數據。很快您就會質疑,違背客戶機-無狀態(tài)-服務器約束是否真的是一個好主意。(實際上,很多開發(fā)人員都不了解這個約束。)

使分布式緩存變?yōu)椴豢赡?/font>

融入式服務器端 Web 應用程序的第二個嚴重后果在于:它實際上不能利用 REST 的第一類支持進行資源緩存。引用 Fielding 的話來說,“添加緩存約束的優(yōu)點是可以部分或完全避免某些交互操作,從而可以通過減少一系列交互的平均延遲來提高效率、可伸縮性以及用戶可以感受到的性能。不過這樣做的代價是如果緩存中的陳舊數據與通過將請求直接發(fā)送給服務器而獲得的數據有很大區(qū)別,那么緩存的可靠性就降低了。”

我們可以將融入式 Web 應用程序近似地看作一個活動實體,它會根據用戶提供的新輸入內容、其他人輸入的新內容以及新的后臺數據而不斷發(fā)生變化。由于服務器必須根據多個用戶與應用程序的交互來生成每個頁面,因此我們實際上無法兩次生成相同的文檔。因此,Web 瀏覽器或代理服務器無法緩存服務器資源。

有幾種解決方案可以用來處理資源無法緩存的問題。一種就是創(chuàng)建細粒度的資源在服務器端的緩存,這樣服務器就可以通過預先組合好的部分來構建一個粗粒度的頁面,而不是通過基本元素(HTML 和數據)從頭開始一步步地構建這種頁面了。但是問題依然存在:每個請求都會導致大量的服務器處理,這會損害系統(tǒng)的可伸縮性,還可能會對用戶感受到的響應性造成負面影響。

無法提供可緩存資源的另外一個結果是:動態(tài)程度相當高的 Web 應用程序必須顯式地禁止搜索引擎和其他類型的 “機器人”作出請求,因為處理這類請求的成本都非常昂貴;而在符合 REST 準則的應用程序中,只需一次性地將某個資源提供給那一類 “機器人”,然后對它們的后續(xù)訪問發(fā)送一條簡單的 “Not-modified” 消息即可。

不使用 Ajax 的客戶端的處理

隨著訪問 Web 應用程序的用戶越來越多,系統(tǒng)需要的資源也會逐漸增加??梢宰尫掌鱽硖幚磉@一切,但將需要容量更大的服務器或集群服務器(服務器端狀態(tài)在集群環(huán)境中并不太適用)。但如果將處理分布到客戶機上,那么每增加一名新用戶,您就相當于有了一臺支持部分新負載的新電腦。如果將會話狀態(tài)分布到客戶機上,那么就有了一個無狀態(tài)的服務器 —— 這是可伸縮 Web 應用程序中令人滿意的一項特性。這看上去應該是種非常明智的做法,那么為什么不按這種方法設計所有融入式 Web 應用程序呢?在 Ajax 出現之前,答案非常簡單:每次用戶訪問一個新的 Web 頁面時,應用程序狀態(tài)時就會被銷毀。

每次訪問一個 Web 頁面時,都要下載一個或一組包含內容的文件(包含在結構化信息中的數據,例如表和列表),以及影響內容外觀的樣式(例如,紅色文本)。在 Web 瀏覽器中,這些信息都是作為文檔對象的抽象集來查看的。下面的列表為例:

  • Ford
  • BMW
  • Toyota

瀏覽器會認為這個 HTML 是一個 “無序清單” 對象,其中包含了 3 個列表元素;每個列表元素都包含文本。整個文檔可視為一個復雜的相關對象樹。當我們從一個頁面瀏覽到另外一個頁面時,瀏覽器就會銷毀當前頁面的對象樹,并為下一頁創(chuàng)建一個新的對象樹。

但是為什么要在一個負載過重的服務器上集中這么多的資源消耗呢?從理論上來說,我們什么時候可以將處理和內存需求分布到客戶機呢?簡單的答案是給定傳統(tǒng) Web 瀏覽器約束,這是不可行的(請參看 不使用 Ajax 的客戶端處理)。但是 Ajax 架構風格使開發(fā)人員可以將處理和狀態(tài)需求分布到客戶機。請繼續(xù)閱讀,學習為什么選擇使用 Ajax 風格的融入式應用程序可以繼續(xù)遵循 REST 準則,并充分利用它的優(yōu)勢。

Ajax 和 REST

正如我們前面看到的一樣,傳統(tǒng)的服務器端 Web 應用程序將數據的標識和服務器上的動態(tài)數據元素合并在了一起,并將所構成的完整 HTML 文檔返回給瀏覽器。Ajax 應用程序在其主要 UI 和瀏覽器中的主要邏輯方面有所不同;基于瀏覽器的應用程序代碼可以在必要時獲取新的服務器數據,并將這些數據織入當前頁面(請參看 參考資料 中 Jesse James Garrett 有關 Ajax 的啟蒙文章)。呈現和數據綁定的位置看起來可能是一個實現細節(jié),但是這種區(qū)別會導致完全不同的架構風格。

利用有狀態(tài) Web 客戶機的優(yōu)點

人們通常將 Ajax 應用程序描述成無需在每次點擊時徹底地刷新整頁的 Web 頁面。盡管這個描述非常確切,但是根本的動機在于徹底刷新整頁會令用戶不耐煩,從而無法獲得愉快、融入式的用戶體驗。從架構的角度來看,整個頁面全部刷新的設計甚至非常危險,這種設計使您無法選擇在客戶機存儲應用程序狀態(tài),這可能會導致妨礙應用程序充分利用 Web 最強大的架構設計點的設計決策。

Ajax 讓我們不需要進行完全刷新就可以與服務器進行交互,這一事實使有狀態(tài)客戶機再次成為可用選擇。這一點對于動態(tài)融入式 Web 應用程序架構的可能性有深遠的影響:由于應用程序資源和數據資源的綁定轉換到了客戶端,因此這些應用程序都可以享受這兩個世界中最好的東西 —— 融入式 Web 應用程序中動態(tài)、個性化的用戶體驗,以及遵守 REST 準則的應用程序中簡單、可伸縮的架構。

緩存 Ajax 引擎

設想一下,將 Amazon.com 徹底重新實現為一個 Ajax 應用程序 —— 一個 Web 頁面可以從服務器上動態(tài)獲取所有的數據。(出于商業(yè)原因,Amazon 可能并不希望這樣做,不過那是其他文章討論的話題了。)由于現在有很多 UI 和應用程序邏輯都可以在客戶機而不是在服務器上運行,根據 Garrett 的說法,最初加載頁面時需要下載 Amazon 的 Ajax “引擎”。這個引擎包含大量應用程序邏輯(以 JavaScript 代碼實現),另外還有此后將使用從服務器上異步獲取的數據填充的 UI 框架(見圖 4):


圖 4. 融入式 Ajax 應用程序

Ajax 引擎一個有趣的特征就是:盡管它包含了很多應用程序邏輯和表示框架元素,但是如果經過恰當的設計,它可以不包含任何業(yè)務數據或個性化內容。應用程序和表示都凍結在部署時。在典型的 Web 環(huán)境中,應用程序資源可能 6 個月才會變更一次。這意味著負責隔離應用程序資源和數據資源的 Ajax 引擎是高度可緩存的。

Dojo Toolkit 就是一個很好的例子(請參看 參考資料)。Dojo 提供了構建時工具來創(chuàng)建一個包含所有應用程序邏輯、表示和風格的壓縮 JavaScript 文件。由于它終究只是一個文件,因此 Web 瀏覽器可以對其進行緩存,這意味著我們第二次訪問啟用 Dojo 的 Web 應用程序時,很可能就會從瀏覽器緩存中加載 Ajax,而不是從服務器上加載它。我們可以將這種情況與高度融入化的服務器端 Web 應用程序進行一下對比,后者每次請求都會導致大量的服務器處理,因為瀏覽器和網絡中介不能對緩存不斷變化的資源。

由于 Ajax 應用程序引擎只是一個文件,因此它也是可以使用代理緩存的。在大型的企業(yè)內部網中,只要有一名員工曾經下載過某個特定版本的應用程序的 Ajax 引擎,其他任何人都可以從內部網網關上上獲取一個緩存過的拷貝。

因此對于應用程序資源來說,經過良好定義的 Ajax 應用程序引擎符合 REST 準則,與服務器端 Web 應用程序相比,它具有顯著的可伸縮性優(yōu)勢。

緩存 Ajax 數據

用戶瀏覽一個 Ajax Web 站點,加載 Ajax 應用程序引擎,最好是從瀏覽器緩存中加載的,否則就從本地代理服務器加載。那么對于業(yè)務數據來說情況如何呢?由于應用程序邏輯和狀態(tài)都在瀏覽器上駐留并執(zhí)行,因此應用程序與服務器的交互就與傳統(tǒng) Web 應用程序的方式有很大的不同。不需要獲取混合的內容頁面,只需要獲取業(yè)務數據即可。

現在回到 Amazon.com 的例子上來,假設我們點擊了一個鏈接,要查看有關設計模式的一本書籍。在 Amazon.com 目前的應用程序中,鏈接點擊操作會發(fā)送很多標識所請求的資源的信息。它還會發(fā)送很多會話狀態(tài)信息,這讓服務器可以創(chuàng)建一個新頁面,其中可以包括之前的狀態(tài)(例如最近查看的內容)、個性化信息(例如您在 1999 年購買的書籍)以及實際的業(yè)務資源本身。應用程序是動態(tài)且高度個性化的 —— 但是卻不能緩存,也無法伸縮(正如 Amazon 所示范的一樣,這些架構問題都可以通過投入大量資金構建基礎設施來克服)?,F在我們考慮一下這個操作在(假想的)Ajax 版本的應用程序中的情況。對于 “最近查看的內容” 并不需要進行處理。當我們點擊某個鏈接時,這些在頁面上已經存在的信息并不會消失。有兩個請求很可能會與設計模式的書籍有關:

  • /Books/0201633612(其中 0201633612 是設計模式書的 ISBN 號)
  • /PurchaseHistory/0201633612/bhiggins@us.ibm.com

第一個假定的請求會返回有關書籍的信息(作者、標題、簡介等);其中并沒有包含特定于用戶的數據。特定于用戶的數據意味著當更多用戶請求相同的資源時,很可能會從 Internet 上的中間節(jié)點上來檢索緩存版本,而不是從原始服務器上檢索這些資源。這種特性會降低服務器和總體網絡負載。另外一方面,第二個請求包含了特定于用戶的信息(Bill Higgins 的購買該書的歷史記錄)。由于這些數據包括一些個性化信息,因此只有一名用戶需要從這個 URI 中獲取并緩存數據。盡管這種個性化數據并沒有非個性化數據的可伸縮特性,但是重要的問題是這些信息都是直接從 URL 中獲取的,因此都具有這樣的正面特征:它們都不會妨礙其他可緩存的應用程序和數據資源的緩存。

Ajax 和健壯性

Ajax 架構風格的另外一個優(yōu)點是它可以輕松處理服務器的故障。正如我們前面介紹的一樣,具有融入式用戶體驗的服務器端 Web 應用程序通常會在服務器上保存大量的用戶會話狀態(tài)。如果服務器發(fā)生了故障,會話狀態(tài)就丟失了,那么用戶就會體驗到非常奇怪的瀏覽器行為(“為什么我又回到主頁上來了?我的購物車中的東西都到哪里去了?”)。在采用有狀態(tài)客戶機和無狀態(tài)服務的 Ajax 應用程序中,服務器崩潰/重新啟動對于用戶來說都是完全透明的,因為服務器崩潰不會影響會話狀態(tài),這些都保存在用戶的瀏覽器中;無狀態(tài)服務的行為是冪等的,可以由用戶請求的內容來單獨確定。





回頁首


承諾和問題

對于我們稱為融入式 Web 應用程序的那些 Web 應用程序來說,設計良好的 Ajax/REST 應用程序在用戶體驗、響應性和可伸縮性方面都遠遠超過傳統(tǒng)的服務器端 Web 應用程序。然而,一種架構風格的運行時特征對于軟件項目和 Web 應用程序來說并非是決定成功的惟一因素。在創(chuàng)建 Ajax/REST 應用程序時有一些非常困難的非運行時問題,包括大規(guī)模 JavaScript 開發(fā)、文化問題和打包問題。我們將在另外一篇文章中討論有關文化的問題,其他內容留待我那些研究 Ajax 的同僚們去處理。

本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現有害或侵權內容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯系客服!

聯系客服