- 浏览: 91789 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
clcai:
[/color][color=green]
div实现模态窗口(转) -
clcai:
[align=left][/align][size=small ...
div实现模态窗口(转) -
reyesyang:
很有帮助的文章。
[翻译]来自Rails Envy的Rails Cache教程 part1 -
JasonChi:
Hooopo 写道google group的ROR北京社区在哪 ...
rails 学习(转) -
Hooopo:
google group的ROR北京社区在哪里啊
rails 学习(转)
http://railsenvy.com/2007/2/28/rails-caching-tutorial
整个教程有两部份,第一部分也就是这篇讲page cache,第二篇讲其它的cache。这篇文章其实主要还是讲基础,不过结合了一些示例,并配上生动的语言。
合适的缓存机制可以提升Rails应用的性能。而Page Cache就是Rails中最高效的缓存。Page Cahe机制可以让每次请求不用进行数据库查询,甚至不用触动到Ruby解析器,完全由前端web服务器来进行服务。
配置
如果你想在devlopment模式启用cache机制,就需要修改/config/environments/development.rb文件,找到下面这行并把配置项改为true:
CODE:
config.action_controller.perform_caching = true
页面缓存
两种很适合缓存页面的情况:
当页面对于所有用户都是相同的
当页面是公开的,而且无须用户认证
假设环境是在一个不经常改动的Blog页面中。。。Controller的代码应该貌似这样:
CODE:
class BlogController < ApplicationController
def list
Post.find(:all, :order => "created_on desc", :limit => 10)
end
...
如果想要缓存list action中显示的页面就在代码中加入:
CODE:
class BlogController < ApplicationController
caches_page :list
def list
Post.find(:all, :order => "created_on desc", :limit => 10)
end
...
这样,在下次请求时就会生成并返回缓存好的list.html页面,下下次的话就是直接返回缓存页面。
如果使用的是mongrel,对list action进行配置后的第一次请求时,/logs/development.log会有貌似以下的记录:
CODE:
Processing BlogController#list (for 127.0.0.1 at 2007-02-23 00:58:56) [GET]
Parameters: {"action"=>"list", "controller"=>"blog"}
SELECT * FROM posts ORDER BY created_on LIMIT 10
Rendering blog/list
Cached page: /blog/list.html (0.00000)
Completed in 0.18700 (5 reqs/sec) | Rendering: 0.10900 (58%) | DB: 0.00000 (0%) | 200 OK [http://localhost/blog/list]
Cached page: /blog/list.html这行记录表明了页面已被导入,并存放在 /public/blog/list.html 位置下。在这个文件中没有一丁点Ruby代码。下一次请求到来时又会绕过Rails再次返回这个静态页面,这就提升了效率,降低了服务器的开销。
这样的话,如果是有动态表单的页面和经常更新的页面,Page Cache就不太适合了。不过还可以采用其它的缓存机制,请留意本教程的Part2。(卖广告:>)
如果在代码里再加上这一句:
CODE:
caches_page :show
当URL指向/blog/show/5访问id为5的blog日志时,请问调用的是哪个缓存文件(或其文件名为什么)?
答案是:/public/blog/show/5.html
看看下面的例子(URL和对应的缓存文件):
CODE:
http://localhost:3000/blog/list => /public/blog/list.html
http://localhost:3000/blog/edit/5 => /public/edit/5.html
http://localhost:3000/blog => /public/blog.html
http://localhost:3000/ => /public/index.html
http://localhost:3000/blog/list?page=2 => /public/blog/list.html
伊,等等,不太对阿。第一行和最后一行怎么返回的缓存文件一样?Page Cache忽略了URL附带的参数了。
在采用分页的页面怎么使用Page Cahe
要缓存不同的文件,只能创建不同格式的URL了。使用“/blog/list?page=2”的话会出问题,那就使用“/blog/list/2”吧。这样子的话,数字2就是作为params[:id]了,那就要修改路由规则(/config/routes.rb)了:
CODE:
map.connect 'blog/list/:page',
:controller => 'blog',
:action => 'list',
:requirements => { :page => /\d+/},
:page => nil
配合新的路由,页面的链接也要改一下:
CODE:
<%= link_to "Next Page", :controller => 'blog', :action => 'list', :page => 2 %>
上面这句生成的URL就是“/blog/list/2”了,访问这URL时会以下两件事会发生:
Rails应用把数字2作为params[:page]
这个页面被缓存为/public/blog/list/2.html
上面这个示例告诉我们,如果要使用PageCache机制的话,那就要对附加参数做一下处理,让附加参数成为URL的一部分。
清理Cache
页面失效了怎么办?那就清理掉失效页面呗!
以下两行代码可以清除上面例子中生成的Cache:
CODE:
# This will remove /blog/list.html
expire_page(:controller => 'blog', :action => 'list')
# This will remove /blog/show/5.html
expire_page(:controller => 'blog', :action => 'show', :id => 5)
那就要在每次添加/改动/删除blog日志时都进行这些操作。要把这两行代码加入action中吗?不,有优雅的解决方法。。。
Sweepers
Sweepers是一些能在页面失效是删除旧的缓存的代码。Sweepers监视Model的一举一动,当Model进行CRUD时,Sweepers得知后就会去把相应的缓存删除掉。
Sweepers的操作应该放在一个Controller中,而且作者认为还应该与其它的controller分离开。那就要改动配置文件/config/environment.rb:
CODE:
Rails::Initializer.run do |config|
# ...
config.load_paths += %W( #{RAILS_ROOT}/app/sweepers )
# ...
end
友情提示,改动环境变量之后记得重启服务器。
如上改动后在/app/sweepers创建sweepers,文件/app/sweepers/blog_sweeper.rb应该是这样:
CODE:
class BlogSweeper < ActionController::Caching::Sweeper
observe Post # This sweeper is going to keep an eye on the Post model
# If our sweeper detects that a Post was created call this
def after_create(post)
expire_cache_for(post)
end
# If our sweeper detects that a Post was updated call this
def after_update(post)
expire_cache_for(post)
end
# If our sweeper detects that a Post was deleted call this
def after_destroy(post)
expire_cache_for(post)
end
private
def expire_cache_for(record)
# Expire the list page now that we posted a new blog entry
expire_page(:controller => 'blog', :action => 'list')
# Also expire the show page, incase we just edited a blog entry
expire_page(:controller => 'blog', :action => 'show', :id => record.id)
end
end
生成Sweepers可以使用插件Sweeper Generator,可以参看martin的介绍。
友情提示:用after_save方法可以代替上面的after_create和after_update两个方法。
要调用Sweepers,在文件/app/controllers/BlogController.rb中应这些写代码:
CODE:
class BlogController < ApplicationController
caches_page :list, :show
cache_sweeper :blog_sweeper, :only => [:create, :update, :destroy]
...
当创建一个Blog日志时,会在logs/development.log中发现这样的记录:
CODE:
Expired page: /blog/list.html (0.00000)
Expired page: /blog/show/3.html (0.00000)
hoho~ sweepers生效了。
在Apache/Lighttpd的漂亮演出
许多Rails应用都会使用Apache作为前端,用Mongrel / Lighttpd处理动态的RoR请求。要使Rails的Page Cache机制生效,告诉服务器当请求来的时候去哪里查找缓存页面。下面是配置Apache为例,修改httpd.conf文件:
CODE:
<VirtualHost *:80>
...
# Configure mongrel_cluster
<Proxy balancer://blog_cluster>
BalancerMember [url]http://127.0.0.1:8030[/url]
</Proxy>
RewriteEngine On
# Rewrite index to check for static
RewriteRule ^/$ /index.html [QSA]
# Rewrite to check for Rails cached page
RewriteRule ^([^.]+)$ $1.html [QSA]
# Redirect all non-static requests to cluster
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://blog_cluster%{REQUEST_URI} [P,QSA,L]
...
</VirtualHost>
在lighttpd中应该是类似这样:
CODE:
server.modules = ( "mod_rewrite", ... )
url.rewrite += ( "^/$" => "/index.html" )
url.rewrite += ( "^([^.]+)$" => "$1.html" )
这样代理服务器就会/public目录下查询cache文件,这样你可能会想要修改cache文件的目录。
把Cache文件分离处理
首先这样修改/config/environment.rb:
CODE:
config.action_controller.page_cache_directory = RAILS_ROOT + "/public/cache/"
这样就让Rails在/public/cache/下生成缓存文件了。接着就修改前端服务器Apache的配置文件httpd.conf:
CODE:
# Rewrite index to check for static
RewriteRule ^/$ cache/index.html [QSA]
# Rewrite to check for Rails cached page
RewriteRule ^([^.]+)$ cache/$1.html [QSA]
清理单个局部或者全部缓存
当开始使用页面缓存的时候可能会发现,一旦对模型有CRUD操作,基本上所有的缓存都要被清除掉。那直接删除了生成的缓存文件岂不是更好更快。
首先要把cache文件分离出来,这在上一步已经做了。下面的代码直接删除cache文件夹下的所有文件,并记录事件到日志中:
CODE:
class BlogSweeper < ActionController::Caching::Sweeper
observe Post
def after_save(record)
self.class::sweep
end
def after_destroy(record)
self.class::sweep
end
def self.sweep
cache_dir = ActionController::Base.page_cache_directory
unless cache_dir == RAILS_ROOT+"/public"
FileUtils.rm_r(Dir.glob(cache_dir+"/*")) rescue Errno::ENOENT
RAILS_DEFAULT_LOGGER.info("Cache directory '#{cache_dir}' fully sweeped.")
end
end
end
FileUtils.rm_r 方法删除目录下所有文件。这就相当于执行了多次的expire操作。也可以删词cache目录的子目录下的文件,如下面代码展示的对 /public/blog目录下所有文件进行删除:
CODE:
cache_dir = ActionController::Base.page_cache_directory
FileUtils.rm_r(Dir.glob(cache_dir+"/blog/*")) rescue Errno::ENOENT
更高级的Page Cache技巧?
在大型Web应用中Page Cache的处理将会是非常复杂的。
Rick Olson写了Referenced Page Caching Plugin用数据库来对缓存页面进行跟踪。README中有一些示例展示。
Max Dunn写了篇文章 Advanced Page Caching,向我们展示了他如何使用cookies动态地改变页面缓存处理基于用户角色的wiki页面。
最后,Page Cache还无法解决缓存xml文件,Mike Zornek讲述了这个问题并提出了一些方法,详见这里。
Page Cache怎么测试?
Rails本身并没有提供给我们。Damien Merenne写了一个插件 swank plugin试图解决这个问题。试一下。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/joliny/archive/2008/03/05/2152241.aspx
发表评论
-
Can't install RMagick 2.13.1. Can't find MagickWand.h.
2012-01-09 14:45 2180=== ln -s /usr/local/include/ ... -
rails 3.1 mysql2.gem 安装
2011-11-11 15:20 778http://www.cnblogs.com/ilazysof ... -
用imagemagick和tesseract-ocr破解简单验证码 自我补充记录
2011-10-13 16:28 1898http://hooopo.iteye.com/blog/99 ... -
mac虚拟机本地通过git上传项目到github时出现的诡异问题
2011-10-02 23:27 1973错误为: Permission denied (public ... -
mac rails3.1 启动mysql报错解决
2011-09-27 23:18 1179/Library/Ruby/Gems/1.8/gems/m ... -
windows rails+apache+ssl 配置
2011-09-08 19:51 1070apache 中ssl配置详见: http://apps.hi ... -
ruby on rails linux部署环境下定时任务解决小记
2011-08-31 18:09 989原本系统在开发环境下的定时任务用的是 rufus-schedu ... -
rails rake 用法说明
2011-08-31 11:44 1413原文:Ruby on Rails Rake Tut ... -
郁闷的部署
2011-08-22 16:11 700今天想给跑在windows下的系统用apache+mongre ... -
浅析Ruby on Rails部署方案(转)
2011-08-22 14:37 880前言 两年过去了,随着客户端数量的不断增加、客户端功能的增加 ... -
rails 学习(转)
2011-08-17 11:15 8521. 书籍: rails 圣经: Agile Web De ... -
AJAX file uploads in Rails using attachment_fu and responds_to_parent
2011-08-12 17:32 532http://khamsouk.souvanlasy.com/ ... -
rails的REST特性简记(转)
2011-07-11 14:53 8241.关于REST的URL的详细讨论,参见《RESTful Ra ... -
ubuntu 10.10 rails 安装
2011-07-09 00:13 690http://floger.iteye.com/blog/93 ... -
rails rmagic安装问题 解决
2011-06-14 12:36 980一开始手动下载imagemagick安装的,结果配置出现一些问 ... -
如何用nginx+passenger部署Rails(转)
2011-06-10 15:28 1707以前一直用apache+passenger ... -
rails + sqlserver 2005 分页 问题记录
2011-06-08 19:20 812都说sqlserver + rails 用着别扭,终于体会到了 ... -
centos 5.5 rails 安装 参考
2011-05-19 17:50 9961.安装gcc yum install gcc-c++ y ... -
centos 5.5 rails 安装 参考
2011-05-19 16:40 1093这二天部署一个项目,部署在Centos 5.5 下,本来用的u ... -
rails应用与多数据库的连接
2011-04-15 15:20 875rails与多数据库的连接有插件模式,也有原生模式,本文参考互 ...
相关推荐
学习rails和ruby的好教程。赶快下吧!
ruby_on_rails_3_入门教程(中文)
rails学习教程,ruby on rails入门,pdf格式,英文
本书算是最好的rails的与ruby的教程。。。全书共144M,此为part1,还有part2
Ruby On Rails 官方教程,这本书讲解如何使用 Ruby on Rails 框架开发应用,以及如何把应用部署到生成环境。本书使用 Rails 默认的开发工具栈开发了一个完整的社交应用(类似 Twitter)。读完本书后你将掌握如何使用...
Ubuntu系统ruby on rails安装 Ubuntu系统ruby on rails安装 Ubuntu系统ruby on rails安装 Ubuntu系统ruby on rails安装 Ubuntu系统ruby on rails安装 Ubuntu系统ruby on rails安装 Ubuntu系统ruby on rails安装 ...
ruby on rails 教程源码,配合原书使用
《Ruby on Rails Web开发学习实录》 第(2/2)分卷 PDF电子书 高清扫描版
本书算是最好的rails的与ruby的教程。。。全书共144M,此为part2,part1: http://download.csdn.net/detail/jiaoxiaogu/3835985
Ruby On Rails中文教材(PDF)
敏捷Rails中文教程 敏捷Rails中文教程 敏捷Rails中文教程
rails教程rails教程rails教程
ruby2.0安装文件part1 集成了rails framework,sqllite等
本书是中文版,安道翻译的,入门经典,我就是看了它学会rails的!
一本rails的实践的教程,包含一个简单的增删查改实例,结合bootstrap的一个小项目