Web 分散式系統最重要的系統面向發展之一,或許就是確保 Web 文件的存取滿足嚴格的效能與可用性需求。這些需求催生了大量 Web 內容快取與複製的提案。原始方案(至今仍大量部署)針對靜態內容;如今也有許多努力投入支援動態內容——即因請求而產生的文件,以及包含腳本的文件。

Web 代理快取#

客戶端這一側的快取通常發生在兩處:

  • 瀏覽器快取:多數瀏覽器配備簡單的快取機制,文件抓來後存入快取,下次直接從快取載入。客戶端一般可設定何時做一致性檢查。
  • Web 代理快取:客戶端站點常運行 Web 代理,代理接受本地客戶端的請求並轉給 Web 伺服器;回應進來時可以快取結果,必要時回給另一個客戶端——換言之,Web 代理可實作共享快取

在瀏覽器與代理之外,還可以放置涵蓋一個地區甚至一個國家的快取,形成階層式快取(hierarchical caches)。這類方案主要用於降低網路流量,缺點是延遲可能比非階層式方案高——因為客戶端得檢查多層快取而非一層。不過這個額外延遲與文件熱門度強相關:熱門文件在離客戶端較近的快取中找到副本的機率較高。

另一種替代方案是合作式快取(cooperative caching)(或稱分散式快取,distributed caching):Web 代理發生快取未中時,先檢查若干鄰居代理是否有該文件,都沒有才把請求轉給負責該文件的 Web 伺服器。這種方案主要部署在同一組織或機構、位於同一 LAN 的 Web 快取之間。

圖 12-17:合作式快取的原理

延伸討論:合作式 vs. 階層式快取的取捨
  • Wolman 等人(1999)的研究顯示,合作式快取可能只對相對小的客戶群有效(數萬名使用者的量級)——而這樣的客戶群其實用單一代理快取就能服務,通訊與資源開銷還便宜得多。
  • Rodriguez 等人(2001)比較階層式與合作式快取,指出各種取捨:合作式快取之間一般以高速連結相連,抓取文件的傳輸時間遠低於階層式快取;合作式快取的儲存需求也較寬鬆;但階層式快取的期望延遲反而較低。

快取一致性協定#

Web 上部署過多種快取一致性協定:

  • 條件式 get(pull-based):為保證快取回傳的文件一致,某些 Web 代理先對伺服器送出附 If-Modified-Since 請求標頭的條件式 HTTP get,標頭指明快取文件的最後修改時間。只有文件在那之後改過,伺服器才回傳整份文件;否則代理直接把快取版本回給本地客戶端。以第 7 章的術語,這是拉式(pull-based)協定。缺點:每個請求都得聯絡伺服器。

  • 過期時間(Squid 的做法):為了用較弱的一致性換效能,廣泛使用的 Squid 代理在快取文件時指派一個過期時間 T_expire,取決於快取當下文件已多久沒被修改。設 T_last_modified 為文件的最後修改時間(由擁有者記錄)、T_cached 為快取時間,則

    T_expire = α × (T_cached − T_last_modified) + T_cached ,α = 0.2

    (α 值來自實務經驗。)在 T_expire 之前文件視為有效,代理不會聯絡伺服器;過期後代理才請伺服器送新副本(除非沒改過)。α = 0 時就退化成前一種做法。

  • 失效通知(invalidation):改由伺服器在文件被修改時通知各代理。問題是伺服器可能得追蹤大量代理,難免造成可擴充性問題;不過 Cao 與 Liu(1998)證明結合**租約(lease)**與失效通知,伺服器要維護的狀態可以控制在可接受範圍內——狀態量大體由租約的過期時間決定:越短,伺服器要追蹤的快取越少。儘管如此,失效協定在 Web 代理快取上幾乎不曾被採用。

長期未修改的文件不會像新近修改的文件那麼快被檢查——明顯的缺點是代理可能回傳失效的文件(比伺服器上現行版本舊),更糟的是客戶端無從察覺自己剛拿到一份過時文件。

Cao 與 Oszu(2002)比較各種 Web 快取一致性政策的結論是:讓伺服器送失效通知,在頻寬與客戶端感知延遲上可勝過其他所有方法,同時維持快取文件與來源伺服器一致——此結論適用於電子商務應用常見的存取型態。

Web 代理快取的另一個問題是只適用於靜態文件:動態產生的文件往往是唯一的——同一客戶端下次發同樣的請求,回應大概會不一樣(例如許多文件內含每次請求都會更換的橫幅廣告)。這個問題在下文「Web 應用程式的複製」處理。

至於快取汰換策略,研究提案很多,但大體而言,「淘汰最久未使用者(least recently used)」這類簡單策略就已經夠好

Web 託管系統的複製#

隨著 Web 日益成為組織展示自我、直接與終端使用者互動的載具,「維護網站內容」與「確保網站容易且持續可存取」逐漸分家,這催生了內容遞送網路(Content Delivery Networks, CDN):CDN 作為 Web 託管服務,提供基礎設施,把多個網站的 Web 文件分發、複製到網際網路各處。其規模可以很驚人——截至 2006 年,Akamai 據報有超過 18,000 台伺服器分布在 70 個國家。

CDN 的規模要求託管文件自動分發與複製,形成第 2 章討論過的自我管理系統架構。大型 CDN 多半組織成一個回饋控制迴路(feedback-control loop):涉及三類面向——度量估計調整觸發採取適當措施;最後一項再細分為副本放置決策、一致性強制執行、客戶端請求繞送。

圖 12-18:CDN 作為回饋控制系統的一般組織

度量估計#

CDN 在託管複製內容時必須做多方面的取捨:例如文件大量複製時存取時間也許最佳,但同時帶來財務成本與散播更新的頻寬成本。評估 CDN 表現的提案可分為幾類:

  • 延遲度量(latency metrics):量測某動作(如抓一份文件)所需時間。看似簡單,但例如副本放置決策行程需要知道客戶端到某遠端伺服器的延遲時,估計就變得困難,通常得部署第 6 章討論過的全域節點定位演算法。
  • 頻寬度量:有時比延遲更重要的是量測兩節點間的可用頻寬——傳輸大文件時系統回應性大體由文件傳輸時間決定。量測工具很多,但精確量測都不容易。
  • 空間度量(spatial metrics):以網路層路由跳數或自治系統間跳數量測節點距離。但求兩任意節點間的跳數可能非常困難,跳數也未必與延遲相關;而且當 MPLS(multi-protocol label switching)這類低層技術用虛擬電路直接高效轉發封包、繞過網路層路由時,光看路由表是行不通的——封包實際走的路徑可能與路由器表中公告的完全不同。
  • 網路使用度量:多半是消耗的頻寬。以傳輸位元組數計算很容易,但要算得正確,必須考慮文件被讀取、更新、複製的頻率。
  • 一致性度量:告訴我們副本偏離主本的程度,第 7 章連續一致性(continuous consistency)的脈絡下已充分討論過如何量測。
  • 財務度量:完全不技術性,但多數 CDN 是商業營運,財務度量常是決定性的,且與網際網路的實際基礎設施緊密相關——例如多數商業 CDN 把伺服器放在網際網路邊緣,向直接服務終端使用者的 ISP 租用容量。商業模式與技術議題在此交纏,是個遠未被理解的領域。

這些例子說明:光是量測(甚至只是估計)CDN 的效能,本身就可能是極複雜的工作。實務上商業 CDN 真正在乎的是能否達成與客戶簽訂的服務等級協議(service-level agreements)——這些協議往往就簡單地以「客戶多快得到服務」來表述。

調整觸發#

何時、如何觸發調整?簡單模型是週期性估計度量、視需要採取措施——實務上常見:伺服器上的特殊行程收集資訊並定期檢查變化。

週期性評估的重大缺點是會錯過突發變化。最受關注的一種突發變化是閃電人潮(flash crowd):對特定 Web 文件的請求突然暴增,很多時候能拖垮整個服務,進而引發一連串服務中斷——網際網路近年歷史上已有數起見證。

處理閃電人潮很困難:

  • 昂貴的解法是大規模複製網站,一見請求率快速上升就把請求導向副本、卸載主本——這種過度佈建顯然不是正道。
  • 真正需要的是閃電人潮預測器,讓伺服器有足夠時間動態安裝文件副本,情勢吃緊時再重導請求。
  • 預測的難處在於閃電人潮的樣態差異極大。從四個真實網站的存取紀錄可見:有的只是日常起伏帶幾個強峰;有的兩天內出現四次突發人潮,尚存規律、久了或可發現,但發現前傷害可能已經造成;有的請求率幾乎瞬間飆升,任何預測器都會遇到大麻煩;也有的第一個高峰不該觸發調整、第二個才該——這種型態透過執行期分析反而處理得不錯。

圖 12-19:一種正常存取型態與三種反映閃電人潮行為的不同存取型態

延伸方法:線性外插的閃電人潮預測

Baryshnikov 等人(2005)提出持續量測某文件在時間區間 [t − W, t)(W 為視窗大小)內的請求數:區間切成小槽,每槽計數請求,再以簡單線性迴歸擬合出「存取數對時間」的曲線,外插到 t 之後即得請求數預測;若預測超過給定門檻就發出警報。

這個方法對多種存取型態的效果出奇地好。可惜視窗大小與警報門檻高度依賴該 Web 伺服器的流量,實務上需要大量手動微調才能為特定網站配置理想的預測器;如何自動配置閃電人潮預測器仍是未知。

調整措施#

改變 Web 託管服務行為的措施本質上只有三種(彼此相關):改變副本放置、改變一致性強制執行(皆已於第 7 章詳述)、以及決定如何與何時重導客戶端請求。請求重導值得多談,先看 Akamai 如何在實務中處理一致性與複製。

Akamai CDN 的運作

  • 基本想法:每份 Web 文件由一個主 HTML(或 XML)頁面構成,其中內嵌圖片、視訊、音訊等其他文件;顯示整份文件時,瀏覽器也得抓取這些內嵌文件。假設是內嵌文件很少變動,因此適合快取或複製。
  • 內嵌文件平常以 URL 引用;在 Akamai 的 CDN 中,這個 URL 被改成指向一個虛擬幽靈(virtual ghost)——對 CDN 中某台實際伺服器的引用。URL 中同時保留來源伺服器的主機名稱(原因見下)。
  • 解析流程:虛擬幽靈的名稱含一個 DNS 名稱(如 ghosting.com),由一般 DNS 命名系統解析到某台 CDN DNS 伺服器;每台這種 DNS 伺服器都追蹤靠近該客戶端的伺服器(可用前述任何鄰近度度量),實質上把客戶端重導到對它最合適的副本伺服器——可能是最近的、負載最低的、或多種度量的組合(實際的重導政策是專有的)。
  • 客戶端把內嵌文件的請求送往選定的 CDN 伺服器:伺服器沒有該文件時就向原始 Web 伺服器抓取、在本地快取後回給客戶端;已在快取中則立即回傳。副本伺服器必須能對來源伺服器發請求,這正是內嵌文件 URL 也包含來源主機名稱的原因。

圖 12-20:Akamai CDN 的主要運作方式

這套方案強制文件一致性的方式簡單得有趣:主文件改變時,客戶端總是能從來源伺服器抓到新版;內嵌文件則原則上是從鄰近副本伺服器抓的,因此其 URL 除了最終導向 CDN DNS 伺服器的特殊主機名稱外,還包含一個每次內嵌文件變更就更換的唯一識別碼——識別碼一換等於文件改了名字,客戶端被導到某台 CDN 伺服器時,該伺服器在快取中找不到這個名字,就會向來源伺服器抓新的;舊文件因不再被引用,最終被逐出快取。

這個例子已顯示客戶端請求重導的重要性:適當地重導客戶端,CDN 就能掌控客戶端感知的效能,同時兼顧全系統效能(例如避免把請求送往高負載伺服器)。這類適應式重導政策的前提,是把系統當前行為的資訊提供給做重導決策的行程——這又部分回到前述的度量估計技術。

除了政策本身,另一個重要議題是重導對客戶端透明與否。重導技術本質上只有三種:

  • TCP 交遞(TCP handoff):只適用於伺服器叢集,無法擴充到廣域網路。
  • DNS 重導:透明機制——客戶端可完全不知道文件在哪。Akamai 的兩層重導是一例;也可直接用 DNS 回傳多個位址之一。但注意 DNS 重導只能套用在整個網站:個別文件的名稱塞不進 DNS 名稱空間。
  • HTTP 重導:非透明機制——客戶端請求特定文件時,在 HTTP 回應中得到一個替代 URL 並被導向它。重點是這個 URL 對客戶端的瀏覽器可見

HTTP 重導的隱患:使用者可能把被轉介的 URL 加入書籤,使重導政策形同虛設。

Web 應用程式的複製#

以上主要談靜態 Web 內容的快取與複製。實務上 Web 提供的動態內容越來越多,也逐步擴展為可被遠端應用程式呼叫的服務。這些情境下快取與複製同樣大有幫助,只是手法更加微妙:可部署的解法有好幾種,沒有單一最佳解

考慮邊緣伺服器(edge server)情境:假設一個 CDN,每個託管網站有一台**來源伺服器(origin server)**作為所有讀取與更新操作的權威站點;邊緣伺服器負責處理客戶端請求,能儲存來源伺服器所存資訊的(部分)副本。客戶端透過邊緣伺服器請求資料,邊緣伺服器再向該網站對應的來源伺服器取得資訊;來源伺服器內含一個資料庫,回應由它動態產生。邊緣伺服器大致有以下幾種組織方式。

圖 12-21:Web 應用程式中快取與複製的各種替代方案

完全複製#

把來源伺服器儲存的資料完全複製到邊緣伺服器:

  • 適用於更新率低、且查詢需要大範圍資料庫搜尋的情況。所有更新都在來源伺服器進行,由它負責把各副本與邊緣伺服器維持在一致狀態;讀取操作則可在邊緣伺服器進行。
  • 更新率高時,為效能而複製會失敗:每次更新都得跨廣域網路通訊來讓副本回到一致。Sivasubramanian 等人(2004a)顯示,讀取/更新比是決定廣域環境下來源資料庫該複製到什麼程度的關鍵因子。
  • 另一個適合完全複製的情況是查詢通常複雜:以關聯式資料庫而言,就是查詢需要搜尋並處理多個表,如 join 操作。

部分複製#

與複雜查詢相對的是簡單查詢——通常只需存取單一表即可產生回應。此時只在邊緣伺服器存放資料子集的部分複製可能就夠了。

問題在於:手動決定邊緣伺服器需要哪些資料可能非常困難。Sivasubramanian 等人(2005)提議自動化處理——按照 Globule 複製網頁的同一原則來複製資料記錄:來源伺服器分析資料記錄的存取軌跡,據以決定記錄放在哪裡。回顧第 2 章,Globule 的決策是把「資料就位(且可能已複製)後執行讀取與更新操作的成本」納入考量,成本以簡單線性函式表達:各項為某個效能度量 m_k(如消耗頻寬)乘上權重 w_k > 0(表示該度量的重要程度),加總即為成本。

內容感知快取#

部分複製的替代方案是內容感知快取(content-aware caches)

  • 基本想法:邊緣伺服器維護一個依查詢結構組織的本地資料庫,而非像成熟資料庫系統那樣把資料組織成正規化(normalized)的表。也就是說,假設查詢遵循有限數量的模板(templates),能處理的查詢種類是受限的。
  • 收到查詢時,邊緣伺服器將其與可用模板比對,然後在本地資料庫中查找、盡可能組出回應;本地沒有所需資料時,查詢轉給來源伺服器,回應先快取再回給客戶端。
  • 邊緣伺服器實際在做的是檢查「查詢能否用本地儲存的資料回答」——稱為查詢包含檢查(query containment check)。本地資料是先前查詢的回應,因此這個做法在查詢傾向重複時效果最好。

內容感知快取的複雜度來源有三:一、邊緣伺服器的資料要維持一致——來源伺服器必須知道哪些記錄與哪些模板關聯,才能在記錄或表更新時(例如)對適當的邊緣伺服器送失效訊息;二、查詢仍需在邊緣伺服器處理,需要不可忽略的運算力,而資料庫常是 Web 伺服器的效能瓶頸;三、快取跨多表的(複雜)查詢結果、又要能有效執行查詢包含檢查並不容易——結果的組織方式可能與查詢所操作的表的組織方式差異很大。

內容盲快取#

上述觀察引出第三種解法:內容盲快取(content-blind caching)(Sivasubramanian 等人,2006),想法極其簡單:

  • 客戶端對邊緣伺服器提交查詢時,伺服器先為該查詢計算一個唯一的雜湊值,據以查快取確認是否處理過同樣的查詢。
  • 沒處理過:查詢轉給來源伺服器,結果先快取再回給客戶端。處理過:直接回傳先前快取的結果。

主要優點是相較前述資料庫做法,邊緣伺服器需要的運算量大減;缺點是可能浪費儲存空間——快取裡的冗餘資料比內容感知快取或資料庫複製多得多,而冗餘也讓「維持快取新鮮」更複雜:來源伺服器可能得精確掌握哪些更新會影響哪些快取的查詢結果。若假設查詢只能匹配一組預先定義的模板(如前所述),這些問題可以緩解。

這些技術同樣可用於下一代的 Web 服務,但在能認定穩定解法之前,仍需要大量研究。