Caching/Expiring in Rails

10,811 views

Published on

Caching & Expiring in Rails

Published in: Technology

Caching/Expiring in Rails

  1. 1. Caching  With  Rails   By  Carmen  Diaz  Echauri  –  cdechauri@gmail.com   For  www.blazingcloud.net   Rails  version  2.3.8  
  2. 2. Caching  with  Rails   Scaling  your  ApplicaFons   •  Rails  provides  by  default  three  techniques:   –   Page  Caching     –   AcFon  Caching   – Fragment  Caching  
  3. 3. Page  Caching   •  Allows  the  request  for  a  generated  page  to  be   fulfilled  by  the  webserver,  without  ever  having   to  go  through  your  Rails  applicaFon.   Client   Apache   Mongrel   Public/users.html   hOp://localhost:3000/users  
  4. 4. Page  Caching    Next  Fme  we  request  the  same  page,  apache   will  load  the  page  from  the  filesystem  and   send  it  back  to  the  client.   Client   Apache   Mongrel   Public/users.html  hOp://localhost:3000/users  
  5. 5. When  we  might  want  to  page  cached?   •  When  every  user  always  sees  exactly  the  same   content  on  a  page,  even  if  they  are  login  to  the   admin  interface  or  not.  But  It's  always  the   same.   •  It  doesn't  change  so  oWen.  Maybe  once  per   day,  week  or  month.  
  6. 6. Get  started  with  caching….   •  Make  sure   config.acFon_controller.perform_caching  is   set  to  true  for  your  environment.  (config/ environments/development.rb)   config.acFon_controller.perform_caching  =  true  
  7. 7. Page  Caching  
  8. 8. Page  Caching  OpFons   •  format.json  {render  :json  =>  @users}   •  format.iphone   –  /config/iniFalizers/mime_types.rb   •  Mime::Type.register_alias  “text/html”,  :iphone   –  /app/views/users/index.iphone.erb   /public/users.html   /public/users.xml   /public/users.json   /public/users.iphone  
  9. 9. Caching  locaFon   /config/environment.rb   versus  
  10. 10. Page  caching   •  Page  caching  ignores  all  parameters   – hOp://localhost:3000/users?page=1   Will  be  wriOen  out     so  if  someone  request   hOp://localhost:3000/users?page=3  it  will  be  gegng   users.html.  
  11. 11. AcFon  Caching   •  Caching  stored     – Page  Caching   •  Stored  on  Disk   – AcFon  &  Fragment  Caching   •  Use  the  configured  cache  that  we  configure  in  our  rails   instance.    
  12. 12. When  to  do  AcFon  Caching?     •  When  we  need  filters  to  run   – Like  authenFcaFon     Client   Apache   Mongrel   Public/posts.html   hOp://localhost:3000/posts   Run  Filters   (authenFcate)  
  13. 13. AcFon  Caching  
  14. 14. AcFon  Caching   Didn’t  call  the  acFon.  It  loaded  straight  out  of  the  cache   It  executed  the  acFon  
  15. 15. AcFon  Caching  OpFons   /config/environments/development.rb   •  config.cache_store  =  :file_store,  'tmp/cache’      (AcFveSupport::Cache::FileStore)     •  config.cache_store  =  :memory_store    (AcFveSupport::Cache::MemoryStore)     –  {}  in  memory  –background-­‐.  But  you  can  run  out  of  memory   –  No  sharing  between  processes.  You  cannot  use  it  if  you  run  more  than   one  instance  of  your  rails  apps.    
  16. 16. AcFon  Caching  OpFons….   •  config.cache_store  =  :mem_cache_store   •  config.cache_store  =  :mem_cache_store,  :namespace  =>   “store”    (share  apps)   •  config.cache_store  =  :mem_cache_store,  192.168.1.255:1001,   192.168.1.255:1002  (mulFple  servers)    (AcFveSupport::Cache::MemCacheStore)     •  config.cache_store  =  :drb_store   (AcFveSupport::Cache::DRbStore)     •  config.cache_store  =  :custom_store  
  17. 17. AcFon  Caching     •  Features   –  Cached  the  acFon  without  the  layout.   it  will  only  cache  your  acFon  content.   So,  if  you  need  some  sort  of  data  you  might  want  to  use   before_filter  and  set  you  instance  variable      
  18. 18. AcFon  Caching     •  Features  (cont)   •  CondiFonal  AcFon  acFon  using  :if  (or  :unless)  =>  Proc.new{….}  to   specify  when  the  acFon  should  be  cached.     •  Specific  path  using  :cache_path  =>  Proc.new  {  |controller|  or   :cache_path  =>  <method>   :expires_in  =>1.hour  to  specify  when  the  acFon  should  be  cached.       (only  with  memcached  &  rails  >  2.1)  
  19. 19. Fragment  Caching   •  Is  useful  for  dynamic  web  applicaFons   •  Allows  you  to  fragment  many  pieces  of  the  view.   The  pieces  will  be  wrapped  in  a  cache  block  and   served  out  of  the  cache  store  when  the  next   request  comes  in.     Client   Apache   Mongrel   header   hOp://localhost:3000/users   body   widgets  
  20. 20. Fragment  Caching    To  implement  fragment  caching,  you  cache  your  method    in   the  view.   All  keys  are  prefixed  with  "views/"  
  21. 21. Fragment  Caching   You  can  create  your  own  key:  <%  cache("#{@user.id}-­‐recents_joined")  do  %>  or   use  the  rails  way     <%  cache([user,  post,  “toolbar”])  do  %>  
  22. 22. Memcached   •  Is  a  hash  in  memory,    key-­‐value  store    {}  in  memory   (LiveJournal)     –  To  implement  /config/environments/producFon.rb   config.cache_store  =  :mem_cache_store   Same  thing  as  config.cache_store  =  :memory_store     but  it  runs  as  a  separate  process.  You  can  have  several  rails   instances  that  references  the  same  mencached  instance     -­‐  Note:  make  sure  to  install  the  gem  memcached-­‐client.  
  23. 23. Memcached  uses     •  Fragment  Cache  Store   •  AcFon  &  Fragment  Caching  
  24. 24. Memcached  uses     •  As  an  Object  Store   –  Rails.cache.read   –  Rails.cache.write   –  Rails.cache.fetch   –  Rails.cache.delete   –  Rails.cache.exists?   –  Rails.cache.clear   –  Rails.cache.increment   –  Rails.cache.clear  
  25. 25. Memcached  uses    
  26. 26. Memcached  ….  Some  points:   -­‐  Expire  at   def  self.recent      Rails.cache.fetch("recent_posts",  :expires_in  =>  30.minutes)  do          self.find(:all,  :limit  =>  10)    end   end   Run  this  query  every  30  minutes…     -­‐    You  don’t  need  to  have  memcached  installed  to  develop  locally    You  will  get  MemCacheError  (No  connecFon  to  server):  No   connecFon  to  server  Cache  miss:    But,  your  app  will  work  just  fine.  Rails  will  always  execute  the   contents  of  the  fetch  blocks,  and  will  return  nil  for  any  reads.  
  27. 27. Expiring  cached  pages   One’s  first  inclinaFon  may  be  to  expire  pages  in  the  Controller  and  usually  via  the   update  method.     Depending  on  which  technique  you  choose  to  expire  pages  you  can  use  the  method   expire_page  {acFon,fragment}   Instead  of  having  expire  methods  around  your  controllers,  to  clear  cache  files  based   on  when  a  model  is  updated,  sweepers  are  the  way  to  go.  
  28. 28. Expiring  cached  page   AcFonController::Caching::Sweeper  class.  (Share  Objects)     –  Can  observe  Controllers   –  Can  observe  Models   Hooks:   Any  observer  callbacks    aWer  create    aWer  destroy    aWer_save,  etc.   Also  in  any  controllers  callbacks   •  before/aWer_<controller_name>   •  before/aWer_<controller_name>_<acFon>  
  29. 29. Expiring  cached  page   To  implement  sweepers:    Declare  a  new  load  path  in  /config/environment.rb  to  keep  the  sweepers   separate  from  models  and  controllers.   config.load_paths  <<  "#{RAILS_ROOT}/app/sweepers”   Create  the  folder  and  the  observer  files  
  30. 30. Expiring  cached  page   And  then  we  will  tell  the  controller  to  use  the  sweeper   cache_sweeper  :user_sweeper,  :only  =>  [:create,  :update,  :destroy]   When  to  call  the  method   Observe  the  model  
  31. 31. Expiring  cached  page  
  32. 32. Another  way  to  expire.   Clearing  the  cache   And  you  could  use  it  in  a  cron  call…  
  33. 33. Some  thoughts    ImplemenFng  page  caching  can  be  easy.  However,  expiring  can  be   prove  to  be  a  bit  more  challenging  .   •  I  find  tesFng  kind  of  tricky.   •  I  read  through  numerous  blog  posts  but    I  couldn’t    quite  figure  out   how  to  get  things  to  work  as  I  hoped.     •  The  following  are  alternaFves  I’ve  recently  used:     –  Custom  Macthers  by  overwriFng  the  matches?  method   •  AcFonController::Caching::AcFons     –   Build  your  CachePage  /  Fragment  Page  class  and  use     •  AcFonController::Base.expire_page(    )   •  AcFonController::Caching::Fragments   –  expire_fragment   –  fragment_cache_key   –  fragment_exist?   –  read_fragment   –  write_fragment  

×