Ruby on Rails缓存(第二部分)
2007-06-18 11:31
|
原文http://hi.baidu.com/%D0%C7203/blog/item/05ed4ee98256d53eb90e2d33.html 1、为什么要讲解rails缓存 class BlogController < ApplicationController正如你看到的,用户需要进行身份验证,才能看到list这个action,当我们第一次访问list这个action的时候,你可以在/log/development.log中看到: Processing BlogController#list (for 127.0.0.1 at 2007-03-04 12:51:24) [GET]看到 Cached fragment: localhost:3000/blog/list 这句了吗?表明一个文件已经产生了,你可以在这里发现它: /tmp/cache/localhost:3000/blog/list.cache 默认情况下,action缓存将会在/tmp/cache/目录下存放缓存文件,这些缓存文件是 .cache 文件,而不是页面缓存的 .html 文件。缓存文件的路径还包括域名和端口号(localhost:3000,测试的默认地址),当我们使用其他的子域名时,每个子域名都会有自己的缓存路径。 如果你打开list.cache这个文件,你会发现里面都是html内容,就像页面缓存一样。那么两者的区别在哪呢? 当我们再次访问这个地址的时候(刚才是第一次访问),你可以看到/log/development.log Processing BlogController#list (for 127.0.0.1 at 2007-03-04 13:01:31) [GET]可以看到,用于用户验证的before_filter已经执行,需要缓存的action也被执行,所以我们产生了一个访问快速的html静态页缓存。我们的应用执行了用户验证。 必须要重点提醒的是,你的 before_filters 要在你的 caches_action 之前,并在你的controller顶部,否则可能得到错误的html缓存。 3、清除Action缓存 就像上一张文章提到的,需要重新缓存(比如添加了新文章),需要让已有缓存过期。我们可以用sweepers做同样的事情。我们只需要将/app/sweepers/blog_sweeper.rb中的expire_page 改成 expire_action: # Expire the list page now that we posted a new blog entry当然,另一个清除action缓存和片段缓存的方式是执行一个rake任务: rake tmp:cache:clear这将删除所有的.cache文件 4、片段(Fragment )缓存 目前位置我们已经处理了缓存整个页面信息的工作。但是对于动态页面,我们并不需要完全这样做。下面介绍一下片段缓存。 片段缓存可以缓存view文件上的一个部分。 为了缓存一个所有blog文章列表,我们来编辑一下/app/views/blog/list.rhtml <strong>My Blog Posts</strong>“cache do”将在/tmp/cache/localhost:3000/blog/list.cache生成一个片段缓存文件。并使用当前的controller和action对它进行命名。这样当下一次执行到“cache do”的时候,这个缓存文件将被读取。看一下 /log/development.log 这个文件中记录的第一次和第二次访问的情况吧,仔细看! Processing BlogController#list (for 127.0.0.1 at 2007-03-17 22:02:16) [GET]看到一些不同了吗?(译者:我用红色标出了。) 第一次,片段被缓存,第二次则读取了改缓存。但是值得注意的是,得到改文章列表的数据库查询语句还是被执行了两次。但是我们希望在读取缓存的时候,不用去再执行数据库查询语句的啊! 注意,我们缓存的仅仅是在 <%cache do%>和<%end%>之间的内容,而其他的内容每次访问还是会被执行的。所以我们可以在/controllers/blog_controller.rb中增加一个条件: def list这样,数据库查询语句只有在缓存页面未被读取的时候执行。当然,我们也可以将数据库查询语句放到“cache do”之间,但是,我们绝对不希望把model中的方法放到view中,这毕竟是mvc框架!(译者:《Rails敏捷开发》在这个问题上可不这么坚定哦!) 5、清除片段缓存 # Expire the blog list fragment呵呵,上面介绍过的 6、使用片段缓存解决分页缓存 如果我想对我的列表的进行分页,那该如何对每个页面进行缓存呢? 你可能已经意识到,缓存文件的命名是根据他所在的controller和action进行综合命名的。所以当你的controller名称为blog,action为list的时候,你的缓存文件将为/localhost:3000/blog/list.cache 所以缓存分页,需要给缓存一个名字(译者:唯一的名字)。我们的blog_controller.rb将进行改写: def list当然我可以写 "read_fragment({:controller => 'blog', :action => 'list', :page => params[:page] || 1})" ,但是默认的,rails会默认前两个参数,所以我不用写的那么全面(译者:这是rails的灵活的地方,当然为了让其他人明白或者便于自己记忆,你可以写上。这种做法在rails很多地方有体现)。 改写一下/views/blog/list.rhtml <% cache ({:page => params[:page] || 1}) do %>这样,当我访问/blog/list的时候,rails将自动缓存/localhost:3000/blog/list.page=1.cache这个文件,当我访问第二页的时候,将会缓存/localhost:3000/blog/list.page=2.cache。Cool!7、片段缓存的高级命名 大多数时候,我们想给缓存文件起一个名字,那就看一下这个例子吧。 我们需要给我们的每个用户界面增加一个导航条,这个导航条是需要根据每个用户自己设定的项目进行显示的。(译者:用户不同,导航条的功能按钮可能不同) <div id="nav-bar">如果在每个页面显示这个导航条,我还是希望要它能被缓存起来的,这样我可以不同在每个页面都读取一下数据库。但是这个例子中,导航条需要根据不同的用户进行不同的显示,所以我需要对上面的代码进行一个修改: <div id="nav-bar">如果我的user_id是1,那么生成的缓存文件将是/localhost:3000/base/user_tasks.user_id=1.cache,注意:我有一个controller名称为base,里面包含一个名字为user_tasks的action吗?不!这样写只是为了命名方便,这个controller其实不必真的存在的。 8、片段缓存的命名实例 下面是一些其他的片段缓存命名的例子: cache ("turkey") => "/tmp/cache/turkey.cache" 9、同时清理多种片段缓存 上面介绍的分页缓存,将会生成很多的缓存文件,如果想把没一个过期,恐怕要这么来写; expire_fragment(:controller => 'blog', :action => 'list', :page => 1)当然简单的方式是: expire_fragment(%r{blog/list.*})你可以在blog/list下面发现所有的缓存文件,这种方法显然很简洁,但是有3件事情一定要注意:1、这种方式对memcache无效!(作者将会有文章进行讲解,他会告诉我的。) 2、在执行的时候,它会检查每一个文件名是否符合这个正则表达式,所以当你删除400多个缓存的时候,这个将会很大程度降低你的系统性能的(译者:还有比删除rails的session文件更恐怖的事情吗?) 3、注意你的正则表达式,写错的话将会删除掉你不想删的东西的。 10、在哪里储存action或者片段缓存 页面缓存,第一部分提到的,只能在文件系统里储存,对于action缓存和片段缓存,倒是可以有几个方案选择。 1、文件系统,默认的,将缓存的信息文件放入你的硬盘。默认在/tmp/cache/ 这个目录里。 2、内存中 3、DRb Store分布式储存,缓存文件将在"Distributed Ruby"处理过程中储存(译者:没太明白!),当然一个ruby进程可以和所有的服务进行沟通。(原文:DRb Store - Cached pages are stored in a "Distributed Ruby" Process. Basically a separate ruby process that all of your servers can communicate with) 4、memcache储存,memcache是专门为缓存设计的,虽然他不是ruby写的,但是他相当的快,很多大型项目在使用他。(原文:It's not written in Ruby, but it's damn fast and it's what all the big boys use) 对于ruby项目,那个方案比较好呢?开始我们可以使用基本的文件储存,当你的网站越来越知名的时候,你可以使用memcache进行缓存处理。 我觉得使用文件缓存是一个很好的把握缓存技术的开始,如果你想改变缓存方式,你只需要对config/environment.rb进行一个修改即可。 ActionController::Base.fragment_cache_store = :file_store, "/path/to/cache/directory" 11、ActiveRecord查询缓存 最近,第四种缓存方式将在rails上发布,即“ActiveRecord缓存”或称“SQL查询缓存”。该技术目前尚未正式公开,仅在 Rails Edge 中有介绍。 ActiveRecord 查询缓存的功能,和它的字面意思是一样的。而且你不用对它进行任何的设置处理,因为它默认是启动的。我们可以用一个action做一个实验: class BlogController < ApplicationController在使用ActiveRecord查询缓存前,这种查询会执行两次,但是在使用了查询缓存后,同样的写法,数据库查询只会执行一次,第二次同样的查询将会读取缓存。Cool!但是这需要在同一个action中。 这个例子并不是非常全面的反应查询缓存,但是想想当需要进行身份验证的时候,你可能多次的需要进行数据库查询,已保持用户的验证,(译者:比如根据用户cookies中的id查找并得到当前用户实例),这时,查询缓存将会非常有用! 但是,缓存查询只是在一个单一的action开始的时候生效,在action结束的时候就失效了。这里并未真正的设计到储存,所以当进行了增删改的时候,整个缓存将被刷新。如果你需要在多个action或者用户间缓存同一个信息,还是看一下 memcached 吧。(译者:这方面将会和作者和其他人沟通,争取尽快的拿到好的解决方案) 12、高级缓存的选择 除了上面介绍的三种(很快将是四种)缓存方法,还有一些其他的缓存方法介绍给大家: 如果你不想每次都查询数据库,而需要对一个model进行缓存的话,Geoffrey Grosenbach有一篇文章 nice tutorial 和Robot Co-Op 的 cached_model ,你可以看一下。(译者:貌似值得一译啊) 如果想缓存一个model中的方法,你可以看看 this library ,作者 Yurii Rashkovskii. 如果你想给action缓存增加一些功能,可以看一下 Action_Cache plugin 译者:如果还有其他的好方法,请和本文作者联系,或者和我联系。 结束语: 缓存对于大型网站系统来说是非常有用的技术,如果你有更好的意见,请与我们联系: 本文作者:GreggPollack [GreggPollack at Gmail.com], Jason Seifer[jseifer at gmail.com] 本文译者:里克[guxing203 at Gmail.com] 有翻译不对或值得商榷的地方,麻烦留言,大家帮助我进步! |



选择表情