- 浏览: 92104 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
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/3/20/r ... ing-tutorial-part-2
Part1地址:http://www.ruby-lang.org.cn/forums/thread-3158-1-1.html
本教程的编写顺序是按照各个缓存的效率来排序的,Page缓存最快,所以在第一篇教程就介绍了,这篇教程就介绍其它的几种缓存。
Action 缓存
Action缓存和Page缓存十分相似,唯一的区别就是对页面的请求会触及Rails服务器并且filter还是会运行。类似下面代码这样设置Action缓存:
CODE:
class BlogController < ApplicationController
layout 'base'
before_filter :authenticate # <--- Check out my authentication
caches_action :list, :show
可以从代码中看到,用户必须通过认证才能访问list action,当对list进行请求时可以从 /log/development.log看到如下日志
CODE:
Processing BlogController#list (for 127.0.0.1 at 2007-03-04 12:51:24) [GET]
Parameters: {"action"=>"list", "controller"=>"blog"}
Checking Authentication
Post Load (0.000000) SELECT * FROM posts ORDER BY created_on LIMIT 10
Rendering blog/list
Cached fragment: localhost:3000/blog/list (0.00000)
Completed in 0.07800 (12 reqs/sec) | Rendering: 0.01600 (20%) | DB: 0.00000 (0%) | 200 OK [http://localhost/blog/list]
看到“Cached fragment: localhost:3000/blog/list”这行了吗?这表示有缓存文件生成,并且可以找到如下这个文件:
/tmp/cache/localhost:3000/blog/list.cache
默认的情况是, Action缓存会在/tmp/cache/目录下缓存文件,而不是像Page缓存那样直接输出.html文件,是输出.cache文件。如果你在单个应用中包含了一个以上的自域名,缓存文件的路径会包含主机和端口(localhost:3000)。这种情况下每个自域名会缓存在各自的目录下。
如果打开“list.cache”文件,就会看到其中的内容是完整的静态html页面,就像Page缓存的一样。那它们之间有什么区别呢?
如果我们再次对页面做出请求(经过上面的请求之后),来看看/log/development.log:
CODE:
Processing BlogController#list (for 127.0.0.1 at 2007-03-04 13:01:31) [GET]
Parameters: {"action"=>"list", "controller"=>"blog"}
Checking Authentication
Fragment read: localhost:3000/blog/list (0.00000)
Completed in 0.00010 (10000 reqs/sec) | DB: 0.00000 (0%) | 200 OK [http://localhost/blog/list]
如你所见, 前置过滤器Authentication执行了,接着读取了缓存文件,然后输出。所以在这个情况下,依然是输出那个完整的缓存文件,并且还做了用户认证的检查。
这里值得注意的是,action执行前前置过滤器必须被执行。另一方面,你也可能会缓存到一个错误的html文件。
怎样清理Action缓存
如教程Part1中,缓存必须在数据发生变化后被清除掉。这里也是用sweepers,只不过在/app/sweepers/blog_sweeper.rb中"expire_page" 要改为 "expire_action":
CODE:
# Expire the list page now that we posted a new blog entry
expire_action(:controller => 'blog', :action => 'list')
# Also expire the show page, incase we just edited a blog entry
expire_action(:controller => 'blog', :action => 'show', :id => record.id)
也可以用以下的rake任务来清除 Action 缓存和 Fragment 缓存:
CODE:
rake tmp:cache:clear
这个rake任务会删除所有的.cache文件。
Fragment Caching
使用了缓存之后会让应用变得飞快,但是由于这是动态的web应用,缓存整个页面并且总能命中这是不实际的,所以有了Fragment缓存。Fragment缓存能缓存页面中的一部分。
要对Blog应用中Post列表进行Fragment进行缓存就要编辑 /app/views/blog/list.rhtml:
CODE:
<strong>My Blog Posts</strong>
<% cache do %>
<ul>
<% for post in @posts %>
<li><%= link_to post.title, :controller => 'blog', :action => 'show', :id => post %></li>
<% end %>
</ul>
<% end %>
这段cache do的代码会创建文件/tmp/cache/localhost:3000/blog/list.cache,即使用当前的controller和action来进行命名。当下次请求来到并命中cache do部分的代码时就会读取刚刚说到那个缓存文件。让我们查看/log/development.log,来看看第一次和第二次请求中发生了什么:
CODE:
Processing BlogController#list (for 127.0.0.1 at 2007-03-17 22:02:16) [GET]
Authenticating User
Post Load (0.000230) SELECT * FROM posts
Rendering blog/list
Cached fragment: localhost:3000/blog/list (0.00267)
Completed in 0.02353 (42 reqs/sec) | Rendering: 0.01286 (54%) | DB: 0.00248 (10%) | 200 OK [http://localhost/blog/list]
Processing BlogController#list (for 127.0.0.1 at 2007-03-17 22:02:17) [GET]
Authenticating User
Post Load (0.000219) SELECT * FROM posts
Rendering blog/list
Fragment read: localhost:3000/blog/list (0.00024)
Completed in 0.01530 (65 reqs/sec) | Rendering: 0.00545 (35%) | DB: 0.00360 (23%) | 200 OK [http://localhost/blog/list]
有没有感觉到一些冗余?
在第一次请求时生成了缓存,第二次时读取缓存,但是对Posts的SQL查询进行了两次。我们已经对SQL查询的结果缓存到页面中了,我们在缓存之后不用再进行SQL查询了,是吗?
解决这个问题的其中的一个方法就是编辑/controllers/blog_controller.rb,在查询前加上一个条件检查:
CODE:
def list
unless read_fragment({})
@post = Post.find(:all, :order => 'created_on desc', :limit => 10) %>
end
end
现在只会在没有缓存的时候才有查询出现。或者有人会想,把这个请求放到view中的cache do代码块中不就好了吗?但是这个是MVC架构啊。
猜猜怎样清除Fragment缓存
CODE:
# Expire the blog list fragment
expire_fragment(:controller => 'blog', :action => 'list')
没错吧?
在分页中使用Fragment缓存
默认情况下,缓存的命名是通过直接查找当前的controller和action名字来决定的。也就是说controller 为 "blog"并且 action 为 "list"就会缓存到 "/localhost:3000/blog/list.cache"。
在分页的情况下,就要把分页的页码加到缓存文件中。
CODE:
blog_controller.rb
应该类似下面那样处理:
CODE:
def list
unless read_fragment({:page => params[:page] || 1}) # Add the page param to the cache naming
@post_pages, @posts = paginate :posts, :per_page => 10
end
end
在这里代码也可以为:read_fragment({:controller => 'blog', :action => 'list', :page => params[:page] || 1}),但Rails决定了前两个参数,这个无法改变,所以可以省略。
/views/blog/list.rhtml如下:
CODE:
<% cache ({:page => params[:page] || 1}) do %>
... All of the html to display the posts ...
<% end %>
这段代码会在第一次访问 /blog/list时,会创建 /localhost:3000/blog/list.page=1.cache 的缓存文件,按理可知访问分页2时会创建缓存文件/localhost:3000/blog/list.page=2.cache。 Pretty cool!
对Fragment缓存高级命名机制
大多数时候要对cache进行命名,这里有个示例:
话说现代的Web设计中每个页面都有一个用户自定义的导航目录(nav menu)。这里是一个列出用户要完成的项目任务(task)的导航目录:
CODE:
<div id="nav-bar">
<strong>Your Tasks</strong>
<ul>
<% for task in Task.find_by_member_id(session[:user_id]) %>
<li><%= task.name %></li>
<% end %>
</ul>
</div>
这个会在站点的每个页面中显示,如果能在用户第一次访问页面时缓存起来,在之后的访问就不用总是打扰数据库了。那就要对代码进行一点点改动:
CODE:
<div id="nav-bar">
<strong>Your Tasks</strong>
<% cache (:controller => "base", :action => "user_tasks", :user_id => session[:user_id]) do %>
<ul>
<% for task in Task.find_by_member_id(session[:user_id]) %>
<li><%= task.name %></li>
<% end %>
</ul>
<% end %>
</div>
当user_id为1时会创建缓存文件/localhost:3000/base/user_tasks.user_id=1.cache。
Fragment缓存命名示例
这里有些用户命名缓存的例子:
CODE:
cache ("turkey") => "/tmp/cache/turkey.cache"
cache (:controller => 'blog', :action => 'show', :id => 1) => "/tmp/cache/localhost:3000/blog/show/1.cache"
cache ("blog/recent_posts") => "/tmp/cache/blog/recent_posts.cache"
cache ("#{request.host_with_port}/blog/recent_posts") => "/tmp/cache/localhost:3000/blog/recent_posts.cache"
怎样一次sweep多个缓存
上面的分页的Fragment缓存最后生成了很多缓存文件,已知的清除方法只是:
CODE:
expire_fragment(:controller => 'blog', :action => 'list', :page => 1)
expire_fragment(:controller => 'blog', :action => 'list', :page => 2)
expire_fragment(:controller => 'blog', :action => 'list', :page => 3)
.....
但是这里还有一个方法来做这些事情:
CODE:
expire_fragment(%r{blog/list.*})
这样会查找blog/list下的所有cache文件。使用这个方法要明白下面几点:
不能在Memcached(下面会提到)下运行。
这种方法会对所有的cache文件进行正则匹配,如果你的系统中有4,000+个cache文件,这会让你的系统处理很久。
如果你不慎写错了正则表达式,那可能会出大问题。
Action/Fragment缓存的几种缓存机制
Page 缓存只能使用文件系统。Action 和 Fragment缓存就有几种选择:
File Store - (默认) - 把缓存放在磁盘中 (默认在 /tmp/cache/ 目录)。
Memory Store - Rails服务器的处理方法,放在内存。
DRb Store - 使用DRb服务器。
MemCache Store - MemCache是一个高性能的缓存处理程序。注意它不是用Ruby实现的。
作者认为FileStore是一开始最好的选择,在以后升级为其它的方式(如MemCache)也不难,要改变缓存文件存储的位置可以编辑config/environment.rb:
CODE:
ActionController::Base.fragment_cache_store = :file_store, "/path/to/cache/directory"
ActiveRecord查询缓存
这是第四种缓存机制,对这种机制并没有过多的文档,它只出现在 Rails Edge中,现在来介绍一下。
ActiveRecord并不需要做配置,在默认情况下会自动运行。看看这个action:
CODE:
class BlogController < ApplicationController
def some_complex_thing
post = Post.find(1)
# .... Do alot of other stuff
post_again = Post.find(1)
end
end
在没有AR缓存的情况下,SQL查询会进行两次。现在使用了AR缓存后,在第二次的查询会读取第一次查询时生成的缓存。这样就不用担心在单个的Action中两次相同的查询会查询数据库两次了。
不过这里的例子不够直观,但想像复杂的认证代码。很多时候可能会在多种认证方式中进行用户数据的查询,而且这是发布在几个不同地方的代码中的,如果缓存了结果,无疑对性能有提高。
查询缓存在action中第一次查询时缓存,在action结束时清除掉缓存。这里没有真正的存储,当 inserts/updates/deletes 执行时,全部缓存就会刷新。如果你要在多个actions或users间缓存数据,请使用MemCache。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/joliny/archive/2008/03/05/2152244.aspx
发表评论
-
Can't install RMagick 2.13.1. Can't find MagickWand.h.
2012-01-09 14:45 2183=== ln -s /usr/local/include/ ... -
rails 3.1 mysql2.gem 安装
2011-11-11 15:20 783http://www.cnblogs.com/ilazysof ... -
用imagemagick和tesseract-ocr破解简单验证码 自我补充记录
2011-10-13 16:28 1903http://hooopo.iteye.com/blog/99 ... -
mac虚拟机本地通过git上传项目到github时出现的诡异问题
2011-10-02 23:27 1979错误为: Permission denied (public ... -
mac rails3.1 启动mysql报错解决
2011-09-27 23:18 1187/Library/Ruby/Gems/1.8/gems/m ... -
windows rails+apache+ssl 配置
2011-09-08 19:51 1074apache 中ssl配置详见: http://apps.hi ... -
ruby on rails linux部署环境下定时任务解决小记
2011-08-31 18:09 991原本系统在开发环境下的定时任务用的是 rufus-schedu ... -
rails rake 用法说明
2011-08-31 11:44 1414原文:Ruby on Rails Rake Tut ... -
郁闷的部署
2011-08-22 16:11 703今天想给跑在windows下的系统用apache+mongre ... -
浅析Ruby on Rails部署方案(转)
2011-08-22 14:37 883前言 两年过去了,随着客户端数量的不断增加、客户端功能的增加 ... -
rails 学习(转)
2011-08-17 11:15 8601. 书籍: rails 圣经: Agile Web De ... -
AJAX file uploads in Rails using attachment_fu and responds_to_parent
2011-08-12 17:32 535http://khamsouk.souvanlasy.com/ ... -
rails的REST特性简记(转)
2011-07-11 14:53 8281.关于REST的URL的详细讨论,参见《RESTful Ra ... -
ubuntu 10.10 rails 安装
2011-07-09 00:13 696http://floger.iteye.com/blog/93 ... -
rails rmagic安装问题 解决
2011-06-14 12:36 985一开始手动下载imagemagick安装的,结果配置出现一些问 ... -
如何用nginx+passenger部署Rails(转)
2011-06-10 15:28 1709以前一直用apache+passenger ... -
rails + sqlserver 2005 分页 问题记录
2011-06-08 19:20 819都说sqlserver + rails 用着别扭,终于体会到了 ... -
centos 5.5 rails 安装 参考
2011-05-19 17:50 10031.安装gcc yum install gcc-c++ y ... -
centos 5.5 rails 安装 参考
2011-05-19 16:40 1097这二天部署一个项目,部署在Centos 5.5 下,本来用的u ... -
rails应用与多数据库的连接
2011-04-15 15:20 879rails与多数据库的连接有插件模式,也有原生模式,本文参考互 ...
相关推荐
学习rails和ruby的好教程。赶快下吧!
ruby_on_rails_3_入门教程(中文)
rails学习教程,ruby on rails入门,pdf格式,英文
《Ruby on Rails Web开发学习实录》 第(2/2)分卷 PDF电子书 高清扫描版
Ruby On Rails 官方教程,这本书讲解如何使用 Ruby on Rails 框架开发应用,以及如何把应用部署到生成环境。本书使用 Rails 默认的开发工具栈开发了一个完整的社交应用(类似 Twitter)。读完本书后你将掌握如何使用...
本书算是最好的rails的与ruby的教程。。。全书共144M,此为part2,part1: http://download.csdn.net/detail/jiaoxiaogu/3835985
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 教程源码,配合原书使用
本书算是最好的rails的与ruby的教程。。。全书共144M,此为part1,还有part2
rails本地安装包 需要你在安装了ruby一键安装包后安装,内有安装命令步骤。 第一部分在: http://download.csdn.net/source/498734
Ruby On Rails中文教材(PDF)
敏捷Rails中文教程 敏捷Rails中文教程 敏捷Rails中文教程
rails教程rails教程rails教程
最终的示例程序将在外表上和一个同样采用 Rails 开发的微博网站十分相似2。虽然我们将主要的精力集中在这个示例程序上了,但是本书的重点却在于提供一些通用的方法,这样你就会具有坚实的基本功,不论开发什么样的 ...