麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > Ruby > 正文

Ruby on Rails中緩存機制的深度解析

2020-02-24 15:40:34
字體:
來源:轉載
供稿:網友

  今天小編給大家分享一篇Ruby on Rails中緩存機制的深度解析,感興趣的朋友跟小編一起來了解一下吧!

  幾個場景

  首先,讓我先來帶您瀏覽幾個 ChangingThePresent.org 中的頁面吧。我將顯示站點中幾個需要緩存的地方。然后,再指出我們為其中每個地方所做出的選擇以及為實現這些頁面所使用的代碼或策略。尤其會重點討論如下內容:

  全靜態頁面

  幾乎無變化的全動態的頁面

  動態頁面片段

  應用程序數據

  先來看看靜態頁面。幾乎每個站點都會有靜態頁面,如圖 1 所示,其中還有我們的條款和條件。可以通過單擊 register 然后再選擇是否接受用戶協議來瀏覽相應頁面。對于 ChangingThePresent 而言,我們從此頁中刪除了所有動態內容以便 Apache 能夠對它進行緩存。按照我們 Apache 中配置的規則,這些內容永遠都不會由 Rails 服務器生成。因此,我根本無需對其考慮 Rails 緩存。

  圖 1. 用戶協議

2015422163759311.jpg (402×341)

  接下來,再來看看全動態頁面。理論上講,ChangingThePresent 可以有一些動態構建的頁面,但是這些頁面一般很少變化。由于幾乎所有頁面都會顯示用戶是否登錄,因此我們并不怎么關注這種緩存。

  再下來,看看頁面分段緩存。圖 2 中所示的主頁原來是完全靜態的,現在,有一些元素變成了動態的。每天,頁面都會顯示一系列禮物,這些禮物有的是隨機選的,有的則由我們的管理員選定。請注意在標題為 “A Few of our Special Gifts for Mother's Day” 節下的那些禮物,同時也請注意在最右邊顯示為 “login.” 的那個鏈接。此鏈接取決于用戶是否登錄。我們不能緩存整個頁。頁面每天只能改變一次。

  圖 2. 主頁

2015422163836768.jpg (572×433)

  最后再考慮應用程序。除非是在 15 年之前進行網絡沖浪,否則您現在遇到的有趣站點全部都是動態的。現代的應用程序大都分層,而且可以通過在層間添加緩存來使這些分層更加有效。ChangingThePresent 在數據庫層采用了一些緩存。接下來,我將深入討論不同類型的緩存,還會介紹我們為 ChangingThePresent 都采用了何種緩存。

  緩存靜態內容

  Mongrel 是一種 Web 服務器,由 Zed Shaw 利用 2500 行 Ruby 和 C 編寫而成。這個小型的服務器占用內存極少,非常適合 Ruby Web 應用程序,例如 Rails、Nitro、Iowa 等等。Mongrel 可運行于 UNIX? 和 Linux? 上,也可運行在 Win32 上。Mongrel 也經常可以作為代理運行在另一個 Web 服務器(例如 Apache 或 Litespeed)的后端,但這不是必需的 —— 因為 Mongrel 是一種 HTTP 服務器,可以與所有您偏好的 HTTP 工具結合使用。

  除了圖像之外,有關緩存靜態數據的內容,可講的內容不多。由于我們的網站是一個慈善性質的門戶網站,這意味著我們需要更多地關注用戶的感受,比如多加入一些圖像或視頻。但我們的 Web 服務器 Mongrel 并不能很好地服務靜態數據,因此我們使用 Apache 來服務圖像內容。

  我們現在正在著手轉向采用圖形加速器 Panther Express 來緩存最經常被使用的圖像以使其能夠更快地被我們的客戶訪問到。要采取這種策略,我們將需要一個子域 images.changingThePresent.org。Panther Express 直接在圖像的本地緩存中提供圖像服務,然后再向我們發送請求。由于 Panther 服務并不知道我們何時會更改圖像,所以我們使用 HTTP 報頭來使其到期失效,如下所示:

  HTTP 緩存失效報頭

  HTTP/1.1 200 OK

  Cache-Control: max-age=86400, must-revalidate

  Expires: Tues, 17 Apr 2007 11:43:51 GMT

  Last-Modified: Mon, 16 Apr 2007 11:43:51 GMT

  注意這些不是 HTML 報頭。它們與 Web 頁面內容獨立構建。Web 服務器將負責構建這些 HTTP 報頭。像這樣一篇有關 Rails 的文章系列若詳細介紹 Web 服務器配置,未免有點偏題,所以我將直接切入可用 Rails 框架進行控制的緩存內容這一主題(有關 Web 服務器配置的更多內容,請參見 參考資料 中的相關鏈接)。

  頁面緩存

  如果動態頁面不經常更改,可以使用頁面級的緩存。比如,Blog 和公告牌使用的就是這種緩存。通過頁面緩存,Rails 就可以用來構建動態 HTML 頁,并將此頁存儲在公共目錄,這樣,應用程序服務器就可以像服務其他靜態頁面一樣來服務這個動態頁。

  如果頁面已經被緩存,那么就不需要引入 Rails,頁面緩存是 Rails 內速度最快的一種緩存。在最底層,頁面緩存實際上在 Rails 中非常容易實現。頁面和分段緩存二者均在控制器級別發生。您需要告知 Rails 如下內容:

  想要緩存哪些頁面?

  當頁面內容更改時,您如何能在緩存中讓該頁面到期失效?

  可以通過在控制器類中使用 caches_page 指令來啟用頁面緩存。例如,若要在 about_us_controller 緩存 privacy_policy 和 user_agreement 頁面,可以輸入如下代碼:

  清單 2. 啟用頁面緩存

  class AboutController

  caches_page :privacy_policy, :user_agreement

  end

  讓頁面到期失效則可以通過 expire_page 指令來實現。若要在 Rails 調用 new_pages 動作時使上述頁面到期失效,可以使用如下代碼:

  清單 3. 使頁面失效

  class AboutController

  caches_page :privacy_policy, :user_agreement

  def new_pages

  expire_page :action => :privacy_policy

  expire_page :action => :user_agreement

  end

  end

  另外,有幾個小問題需要注意,比如 URL。URL 不能依賴于 URL 參數。例如,應該使用 gifts/water/1 而非 gifts/water?page=1。在 routes.rb 中使用這類 URL 將非常容易。比如,我們的頁面中總是有一個選項卡參數用來顯示哪個選項卡被當前選中。若要將此選項卡作為 URL 的一部分,我們會有如下的路由規則:

  清單 4. 選項卡的路由規則

  復制代碼 代碼如下:

  map.connect 'member/:id/:tab', :controller => 'profiles', :action => 'show'

  對于具有頁面參數的那些列表以及依賴于 URL 參數的其他頁面,也需要采用相同的做法。此外,還需要考慮安全性問題。

  如果頁面已經在緩存內,那么就不會用到 Rails 框架,服務器并不能為您管理安全性。Web 服務器將更樂于在緩存內呈現任何頁面,而不管用戶是否對其擁有查看的權限。所以,如果您很關心頁面可由誰查看,那么就不要使用頁面緩存。

  如果只是想緩存簡單的靜態頁面,那么了解上述內容就應該足夠了。只要內容簡單,實現起來就不難。

  當想要緩存更為復雜的內容時,就需要進行一些權衡取舍了。由于想要緩存的頁面高度動態,所以到期失效邏輯就會變得更加復雜。要處理復雜的到期失效邏輯,將需要編寫和配置定制清理器(sweeper)。在某些控制器擊發時,這些類會從緩存內刪除選定的元素。

  多數定制清理器都會觀察某些模型對象,并根據更改擊發邏輯來使一個或多個緩存頁面到期失效。清單 5 顯示了一種典型的緩存清理器。在此清理器中,開發人員可以定義一個活動記錄事件,比如 after_save。當此事件擊發時,清理器也會擊發,并可讓緩存內的特定頁面到期失效。這個事例所顯示的到期失效基于 expire_page 方法。而很多嚴格的應用程序大都直接使用 Ruby 優秀的文件系統實用工具來顯式地刪除所緩存的頁面。

  清單 5. 一個典型的觀察器

  class CauseController

  cache_sweeper :cause_sweeper

  ...

  class CauseSweeper

  observe Cause

  def after_save(record)

  expire_page(:controller => 'causes', :action => 'show',

  :id => record.id)

  cause.nonprofits.each do |nonprofit|

  expire_page(:controller => 'nonprofits', :action => 'show',

  :id => nonprofit.id)

  end

  end

  end

  現在,您可能會開始感覺到頁面緩存的些許缺點了:復雜性。您雖然可以很好地進行頁面級的緩存,但固有的復雜性卻讓應用程序很難測試,進而會增加系統內出現 bug 的可能性。而且,如果頁面針對每個用戶都會有所不同,或者希望緩存進行過身份驗證的頁面,那么將需要使用頁面緩存之外的方式。對于 ChangingThePresent,我們必須處理兩種情況,原因是我們必須基于用戶是否登錄來更改基本布局上的鏈接。對于大多數頁面,我們甚至都不會考慮使用頁面級緩存。為了讓您能夠深入了解頁面級的緩存,在本文的 參考資料 部分,我特意給出了到一系列有關頁面級緩存的優秀文章的鏈接。接下來,將來深入探究另一種形式的整頁緩存 —— 動作緩存。

  動作緩存

  至此,您已經了解了頁面緩存的主要的優勢及主要的缺點:對于多數頁面檢索而言,根本無需考慮使用 Rails。頁面緩存的優勢是速度快。缺點是缺少靈活性。如果想要基于應用程序內的條件 — 例如,身份認證 — 來緩存整個頁面,那么可以使用動作緩存。

  動作緩存與頁面緩存的工作方式大體相同,但在流程上稍有差別。Rails 在呈現動作前會實際調用控制器。如果由該動作呈現的頁面已經存在于緩存內,那么 Rails 就會在緩存內呈現頁面而不是重新加以呈現。由于現在使用了 Rails,因此動作緩存的速度要比頁面緩存慢一些,但其優點還是很明顯的。幾乎所有的 Rails 認證模式都會在控制器上使用 before 過濾器。動作緩存讓您能夠利用認證及控制器上的任何過濾器。

  從語句構成的角度來看,動作緩存與頁面緩存也應該十分類似,只有指令不太一樣。清單 6 顯示了如何使用 caches_action 指令。

  清單 6. 啟用動作緩存

  class AboutController

  caches_action :secret_page, :secret_list

  end

  緩存到期失效以及清理器的工作方式也應該相同。我們不使用動作緩存的原因與我們不使用頁面緩存的原因是一樣的,但分段緩存對我們來說更重要一些。

  緩存頁面分段

  借助部分緩存,可以緩存頁面的一部分,所緩存的內容很多時候都是布局之類的。要使用分段緩存,開發人員需要先確定分段,方法是通過在 Web 頁面上直接放上 rhtml 指令來包圍一塊內容,如清單 7 所示。在 ChangingThePresent.org 上,我們使用分段緩存來緩存首頁和其他的幾頁。所有的這些頁均使用了數據庫密集訪問而且大都是我們最受歡迎的頁面。

  清單 7. 確定緩存分段

  

  

?

?

  Here, you can make the world a better place with a single gift. Donation gifts

  are also a wonderful way to honor friends and family. Just imagine what we

  can achieve together.

  

?

  

?

?

  

?

  

   'gifts/listable', :locals => { :gift => gift } %>

  

  

?

  ...

  

  在清單 7 中,cache 幫助程序標識所要緩存的分區。第一個參數是標識此緩存分區的惟一名稱。第二個參數包含代碼塊 — 即第一個 do 和最后一個 end 之間的代碼 — 此代碼塊準確地確定了要緩存的 RHTML 分區。

  我們的網站只有一個主頁,所以命名這個頁面非常容易。在其他地方,我們使用一種特定的方法來決定此網頁的 URL 以便惟一標識緩存分段。例如,當我們為特定的內容(比如世界和平或減少貧困)而進行代碼緩存時,我們需要使用清單 8 中的代碼。代碼會為之尋找永久 url,也稱為 permalink。

  清單 8. 通過 URL 標識緩存分段

  

  通常,當緩存單獨頁面時,需要用清理器使之過期失效。有時,使用簡單的基于時間的對象過期更為容易和簡潔。默認地,Rails 并不提供這類機制,但有一種插件名為 timed_fragment_cache 可以實現這一目的。借助這個插件,我可以指定超時,可以在緩存了的內容中指定,也可以在為此頁提供了動態數據的控制器代碼中指定。例如,清單 9 所示的代碼就可以為此頁面構建動態數據。when_fragment_expired 方法只有在相關的緩存分段過期時才會執行。此方法接受參數,用來指定超時的時長,它還接受一個代碼塊,用來指定當內容過期時哪些內容需要重建。我也可以選擇在 rhtml 頁面中指定超時和緩存方法,但我更愿意使用基于控制器的方法。

  清單 9. 基于時間的緩存到期

  def index

  when_fragment_expired 'causes_list', 15.minutes.from_now do

  @causes = Cause.find_all_ordered

  end

  end

  如果能夠容忍數據稍微有些陳舊,那么使用定時的到期機制將可以極大地簡化緩存策略。對于每個被緩存的元素,只需指定想要緩存的內容、可生成動態內容的任何控制器動作以及超時。與頁面緩存類似,如果需要,也可以使用 expire_fragment :controller => controller, :action => action, :id => id 方法顯式讓內容到期。此方法的工作方式與緩存動作和緩存頁面的到期失效是一樣的。接下來,我將介紹如何配置此后端。

  Memcached

  至此為止,我已經介紹了 Ruby on Rails 的頁面和分段緩存模型。看過了 API 之后,現在就可以定義緩存后的數據的去處了。默認地,Rails 將把緩存后的頁面放入文件系統。緩存后的頁面和動作都會進入公共目錄。可以配置緩存后的分段的存儲位置。為此,需要用到內存存儲、文件系統(在所定義的目錄)、數據庫或稱為 memcached 的服務。對于 ChangingThePresent.org,我們使用 memcached。

  可以將 Memcached 想象為一個大型的 hash 圖,這個圖可通過網絡獲得。基于內存的緩存速度快,而基于網絡的緩存的可伸縮性比較好。有了插件支持,Rails 就可使用 memcached 來緩存分段和 ActiveRecord 模型。要使用它,需要安裝 memcached(更多信息,請參看 參考資料)并在 environment.rb(或其他的環境配置文件,比如 production.rb)對它進行配置。

  清單 10. 配置緩存

  config.action_controller.perform_caching = true

  memcache_options = {

  :c_threshold => 10_000,

  :compression => false,

  :debug => false,

  :readonly => false,

  :urlencode => false,

  :ttl => 300,

  :namespace => 'igprod',

  :disabled => false

  }

  CACHE = MemCache.new memcache_options

  清單 10 顯示了一種典型的配置,其中第一行 config.action_controller.perform_caching = true 將啟用緩存。接下來的一行將準備緩存選項。注意,這里的諸多選項是為了讓您可以獲得更多的調試數據、禁用緩存和定義該緩存的名稱空間。在 參考資料 部分給出的 memcached 站點可以找到有關配置選項的更多信息。

  模型緩存

  我們使用的最后一種緩存是基于模型的緩存。我們使用的是稱為 CachedModel 的緩存插件的一種定制版本。模型緩存實際上是一種有限形式的數據庫緩存。緩存很容易按模型啟用。

  要想讓模型使用緩存解決方案,只需擴展 CachedModel 類,而非擴展 ActiveRecord,如清單 11 所示。 CachedModel 擴展 ActiveRecord::Base。ActiveRecord 并非全對象關系型映射層。此框架極大地依賴于 SQL 來執行復雜的特性,而且如果需要,用戶可以很容易降至 SQL。直接使用 SQL 會使緩存出問題,因為緩存層必須處理完整的結果集,而不是單獨一個數據庫行。處理完整的結果集常常會問題不斷,而且如果沒有支持應用程序的深層邏輯,這幾乎不太可能。正由于這個原因,CachedModel 的焦點才會放到緩存單個模型對象上,并只加速返回單行結果的查詢。

  清單 11. 使用 CachedModel

  Class Cause

  大多數 Rails 應用程序都會重復訪問多個條目,例如用戶對象。模型緩存在很多情況下都可以明顯地使速度加快。對于 ChangingThePresent,我們剛剛開始加速基于模型的緩存。

  結束語

  Ruby 雖然是一門生產率極高的語言,但若從性能角度考慮,該語言解釋性的特性讓它并不那么理想。大多數主要的 Rails 應用程序都將會通過有效利用緩存來彌補某些不足。對于 ChangingThePresent.org,我們主要使用分段緩存,并通過控制器使用基于時間的方法來使緩存分段到期失效。這種方式很適合我們的網站,即使其中有一些頁面會基于登錄進來的用戶有所變化。

  我們還研究了使用受 memcached 支撐的 CachedModel 類所能帶來的影響。雖然我們的研究還僅限于緩存對數據庫性能所造成的影響,但早期的結果還是很有希望的。在 下一篇 文章中,我將介紹一些實用技巧,您可以使用這些技巧來為另一個真實世界中的 Rails 示例進行數據庫優化。

  以上就是Ruby on Rails中緩存機制的深度解析了,想必都了解了吧,更多相關內容請繼續關注武林技術頻道。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 日韩色视频在线观看 | 一级毛片免费高清 | 逼特逼视频在线观看 | 看全色黄大色黄大片女图片 | 国产免费网站视频 | 一级成人欧美一区在线观看 | 国内精品久久久久久影视8 嫩草影院在线观看网站成人 | 暴力肉体进入hdxxxx0 | 久久久经典视频 | 久久精品日韩一区 | 国产免费片| 视频一区二区精品 | 九九久久视频 | 麻豆国产一区 | 欧美黑人一级 | 黄网站免费观看视频 | 国产精品久久久久久久久久久久午夜 | 亚洲一区二区免费 | 欧美亚洲免费 | 一分钟免费观看完整版电影 | 国产一区二区三区精品在线观看 | 国产一区二区二 | 久久精品99国产国产精 | 日本不卡二区 | 九九热在线精品视频 | 九九热精 | 毛片毛片 | 免费毛片在线 | 国产wwww | 黄色免费小视频网站 | 国产精品一区在线免费观看 | 免费网站看v片在线a | 毛片一区二区三区四区 | 欧美成人一区免费视频 | 欧美大胆xxxx肉体摄影 | 欧美精品免费一区二区三区 | 久草在线资源福利站 | 午夜视频在线看 | 色骚综合 | 久久久久久久久久久久免费 | 羞羞视频免费入口网站 |