上次讲到一篇关于web浏览器的cache
,而本篇要讲述的是web服务器端的cache。
Web服务器端的cache通过减少对web应用程序的访问和对数据库的访问来减少服务端的负载以及提升客户端的响应速度。
Rails本身提供了对web服务器端cache的很好支持,当然还有一些更加方便的plugin如cache_fu
。
Cache需要关注的问题有几点:
1. Cache对象
2. 在何时以及如何清理cache
3. Cache的存储规则
4. Cache的存储方式
在来研究这几点之前,首先打开rails的cache。
打开Rails的cache很简单,只要在环境对应的配置文件config/environments/*.rb中设置即可:
config.action_controller.perform_caching = true
接下来让我们来一点点看一下Rails如何处理这些问题。
Cache对象
Cache对象可以是page,action或者一个fragment。
a. Page cache
Page cache是最高效的cache机制,对页面的请求完全由web服务器处理,而不需要经过rails应用程序。
让我们通过一个例子来看看rails如何处理page cache:
class ProductsController < ActionController
caches_page :index
def index; end
end
caches_page方法启动这个page cache。在第一次访问products/index时,rails会生成一个文件index.html。对于接下来的request,web服务器会用这个文件来响应请求。
缺点:
1. 适用面比较窄,比如对于需要认证的页面就无法处理。
2. Page cache会忽略参数。如果客户端访问/products/list?page=1,rails会把页面缓存成:/products/list.html。如果客户端下次访问/products/list?page=2时,也会返回/products/list.html。
b. Action cache
我们已经看到,page cache不能处理需要认证的页面。Action cache就是为了解决这个问题,action cache与page cache的区别在于:request会经过web server并且被rails application接收,直到所有的before filters被处理。
例子:
class ProductsController < ActionController
before_filter :authenticate, :only => [ :edit, :create ]
caches_page :index
caches_action :edit
def index; end
def edit; end
end
c. Fragment cache
动态web应用程序的页面往往由多个components组成,而每个component经常需要采取不同的cache、expire策略。针对这个问题,rails提供了fragment cache。
比如对于这个页面:
<% Order.find_recent.each do |o| %>
<%= o.buyer.name %> bought <% o.product.name %>
<% end %>
<% cache do %>
All available products:
<% Product.find(:all).each do |p| %>
<%= link_to p.name, product_url(p) %>
<% end %>
<% end %>
我们没有cache需要实时更新的order部分,而cache了product list部分。
这个cache块会绑定到相应的action,cache页面也会存于相应的action目录下。所以如果一个页面有多个component被cache,则需要添加suffix来区分它们:
<% cache(:action => 'recent', :action_suffix => 'all_prods') do %>
All available products:
...
也可以无需绑定到相应的action,而赋予一个全局的key:
<% cache(:key => ['all_available_products', @latest_product.created_at].join(':')) do %>
All available products:
<% end %>
清理cache
对于上面几种情况,都有相应的cache清理方法。
比如对于page cache和action cache,可以通过在需要清理的action里面调用expire方法来清理:
def create
expire_page :action => :index
expire_action :action => :edit
end
Fragment cache的清理则是这样:
expire_fragment(:controller => 'products', :action => 'recent', :action_suffix => 'all_prods)
expire_fragment(:key => ['all_available_products', @latest_product.created_at].join(':'))
但如上面这样到处写expire方法,显然不是最好的方式。Rails针对此提供了sweeper机制:把cache清理移入一个observer类,此类会监测一个对象的变化,并且通过相应的钩子来清理此对象相关的cache。
class StoreSweeper < ActionController::Caching::Sweeper
# This sweeper is going to keep an eye on the Product model
observe Product
# If our sweeper detects that a Product was created call this
def after_create(product)
expire_cache_for(product)
end
# If our sweeper detects that a Product was updated call this
def after_update(product)
expire_cache_for(product)
end
# If our sweeper detects that a Product was deleted call this
def after_destroy(product)
expire_cache_for(product)
end
private
def expire_cache_for(record)
# Expire the list page now that we added a new product
expire_page(:controller => '#{record}', :action => 'list')
# Expire a fragment
expire_fragment(:controller => '#{record}', :action => 'recent', :action_suffix => 'all_products')
end
end
Cache sweeper在controller里面就是一个after或者aroud filter:
class ProductsController < ActionController
before_filter :authenticate, :only => [ :edit, :create ]
caches_page :list
caches_action :edit
cache_sweeper :store_sweeper, :only => [ :create ]
def list; end
def create
end
def edit; end
end
Cache的存储规则
Cache的存储规则即如何存储cache文件,即cache的存储路径和文件名。
我们可以告诉rails我们想要的存储路径,当然,大部分的时候rails已经有默认的存储路径。而且在不会产生冲突的时候,我们也不需要重新设定。
Page cache:
class WeblogController < ActionController::Base
caches_page :show, :new
end
Page cache生成的cache文件路径类似于:weblog/show/5.html
和
weblog/new.html。
Action cache 和 Fragment cache:
Action cache本质上是在fragment cache的基础上加上一个around filter实现的。所以,它的cache文件名命名规则和fragment cache是一样的:根据host和当前路径。所以,一个url: www.somesites.com/lists/show/1
对应的action cache路径是“www.somesites.com/lists/show/1”。
当一个action有多个不同的路由,它们需要cache到不同的路径时,我们可以通过设定:cache_path选项来根据不同的情况指定cache路径:
caches_action :feed, :cache_path => Proc.new { |controller|
controller.params[:user_id] ?
controller.send(:user_list_url, controller.params[:user_id], controller.params[:id]) :
controller.send(:list_url, controller.params[:id]) }
对于action cache,我们需要区分不同路由的情况。而对于fragment cache,我们需要区分同一个action下的多个fragments的情况,或者是当这个action已经有action cache(占用了默认路径)时:
<% cache(:action => "list", :action_suffix => "all_topics") do %>
# 这会使cache存储于"/topics/list/all_topics",以区分使用了不同suffix的fragments。
expire_fragment(:controller => "topics", :action => "list", :action_suffix => "all_topics")
Cache存储方式
Rails提供了多种cache存储方法。
a. ActiveSupport::Cache::MemoryStore
在同一进程的内存中保存cache,所以如果有多个rails application,它们之间不能共享cache。
ActionController::Base.cache_store = :memory_store
b. ActiveSupport::Cache::FileStore
磁盘存储,这是默认的cache存储方式:
ActionController::Base.cache_store = :file_store, "/path/to/cache/directory"
c. ActiveSupport::Cache::DRbStore
Cache存储于一个单独的共享DRb进程,所有的服务器都可以和这个进程通信。但需要维护一个额外的进程:
ActionController::Base.cache_store = :drb_store, "druby://localhost:9192"
d. MemCached
这种方式跟DRb相似,并且是最流行的production cache方式。
它有几大特性:
- 群组和负载均衡:多个memcached服务器可以进行负载均衡。
- 支持基于时间的过期机制。
- 等。。。
e. ActiveSupport::Cache::SynchronizedMemoryStore
相较于MemoryStore,这是一种线程安全的cache存储。
f. ActiveSupport::Cache::CompressedMemCacheStore
相较于MemoryStore,它对所cache的文件进行了压缩。
g. 自定义cache存储
ActionController::Base.cache_store = MyOwnStore.new("parameter")
更多内容请参考:http://guides.rubyonrails.org/caching_with_rails.html
http://api.rubyonrails.org/classes/ActionController/Caching/Pages.html
http://api.rubyonrails.org/classes/ActionController/Caching/Actions.html
http://api.rubyonrails.org/classes/ActionController/Caching/Fragments.html
分享到:
- 2009-06-22 23:23
- 浏览 1200
- 评论(2)
- 论坛回复 / 浏览 (2 / 2936)
- 查看更多
相关推荐
Examples use Concerns, Russian Doll caching, and Turbolinks, and the book focuses throughout on the right way to use Rails. Additionally, this edition now works on Ruby 2.0, a new release of Ruby ...
Create reusable components that bring Bootstrap and Angular together and effectively use materialized views for caching within Postgres. Get your front end working with Webpack, use Postgres' ...
actionpack-page_caching Action Pack的静态页面缓存(从Rails 4.0的核心中删除)。 介绍 页面缓存是一种缓存方法,其中,响应主体存储在Web服务器可以直接提供服务的文件中: 对端点E的请求到达。 计算其响应并...
Ruby on Rails is the revolutionary online programming tool that makes creating functional e-commerce web sites faster and easier than ever. With the intuitive, straightforward nature of Ruby and the ...
中间人片段缓存像Rails这样的Middleman片段缓存扩展。目的当我们需要构建许多页面时,片段缓存可以减少构建时间。安装在Gemfile上添加以下行: gem 'middleman-fragment-caching' , '~> 0.0.1' 运行捆绑器: $ ...
Rails just keeps on changing. Both Rails 3 and 4, as well as Ruby 1.9 and 2.0, bring hundreds of improvements, including new APIs and substantial performance enhancements. The fourth edition of this ...
Enterprise Rails is indispensable for anyone planning to build enterprise web services. It's one thing to get your service off the ground with a framework like Rails, but quite another to construct a ...
CakePHP是一个开源的PHP on rails的full-stack framework。最开始从Ruby On Rails框架里得到灵感。程序员可使用它来快速创建的Web应用程序。我们的首要目的是使你以一种预置的快速且不失灵活性的方式开展工作。 为...
actionpack-action_caching Action Pack的操作缓存(从Rails 4.0的核心中删除)。 安装将此行添加到应用程序的Gemfile中:gem'actionpack-action_caching',然后执行:$ bundle O actionpack-action_caching Action ...
As a Rails developer, you care about user experience and performance, but you also want simple and maintainable code. Achieve all that by embracing the full stack of web development, from styling with...
Table of Contents Preface ...................................Rails Query Caching 315 Fragment, Action, and Page Caching 316 Index ..................................................................... 319
django-sql-caching 在Django中实现的。 相同查询返回SQL查询结果将仅针对当前请求进行缓存。 缓存将在请求结束时清除。 正在安装 $ pip install django-sql-caching 然后将sql_caching.middleware....
这是一个简单的Rails插件,使用memcache进行操作缓存,并让nginx直接从memcache中提取缓存的页面。 因此,对缓存页面的请求甚至不会打到您的Rails应用服务器上。 它可能不适合所有人,但仍然可以作为实现满足您自己...
跳线 PatchCable是Patcher系列视觉音频编程的概念验证实现,使用Web Audio API...# Turn on caching in development for StimulusReflex bin/rails dev:cache # Install dependencies bundle yarn # Set up database b
Golfscore 前端这是一个尝试构建完全独立于后端应用程序构建和部署的前端的想法的实验。部署策略目前,此应用程序部署在 nginx 之后,它会针对其 xhr 请求向 JSON 后端发出上游请求。 nginx 配置如下所示: upstream...
CakePHP是一个开源的PHP on rails的full-stack framework。最开始从Ruby On Rails框架里得到灵感。程序员可使用它来快速创建的Web应用程序。我们的首要目的是使你以一种预置的快速且不失灵活性的方式开展工作。 为...
Yii是一个全栈式的MVC框架,所谓全栈式指的是Yii框架本身实现了web开发中所要用到的所有功能,比如MVC,ORM(DAO/ActiveRecord), 全球化(I18N/L10N), 缓存(caching), 基于jQuery Ajax支持(jQuery-based AJAX support), ...
Readthis对于5.2之前的Rails版本保持不变,并且不支持新功能。 如果您使用的是Rails 5.2+,则应迁移到内置的Redis缓存。 足迹与表现 查看 安装 将此行添加到您的应用程序的Gemfile中: gem 'readthis' gem '...
Laravel努力剔除开发过程中的痛苦,因此我们提供了验证(authentication)、路由(routing)、session和缓存(caching)等开发过程中经常用到的工具或功能。Laravel的目标是给开发者创造一个愉快的开发过程,并且不...