cache就是缓存,善用缓存可以极大提高网站的性能。rails作为一个full-stack的web应用开发框架,它在这方面做了很多的努力。
我们依次从底层到客户端来了解一下缓存机制的相关细节。
-
rails框架自动进行SQL缓存
rails在内存中缓存了每次sql查询的结果,那么在同一次经过ActionPack时,相同的sql会命中缓存,而提高性能。 -
ActiveRecord层缓存
在rails的model层中可以手动缓存某些业务结果到对应的缓存存储系统里。
如
Rails.cache.fetch(key, expires_in: 1.hour) do
....
end
其中cache的key可以自己指定。这里又不得不提到dog pile effect,也即缓存过期时,多个请求竞争访问,从而导致服务器卡顿现象。race_condition_ttl 和expires_in组合使用可以防止这个问题。
- ActionController层
action缓存:rails4中移除了action的缓存,需要gem(actionpack-action_caching)才能实现。缓存了action response的html结果,但可以进入action-pack进行authenticaion等判断。其内部实现主要是借助fragment cache和各种callback实现的。
如
before_action :authentication, only: :show
cache_action :show, expires_in: 1.hour
page缓存:rails4中移除了page的缓存,需要gem(actionpack-page_caching)才能实现。缓存了action response的html,无需进入action-pack,直接可以返回结果,速度是最快的。
cache_page :show, expires_in: 1.hour
- ActionView层缓存
随着互联网应用的逐渐发展,页面复杂程度加剧,后端无法做到整页面的缓存,只能分割成片段。片段缓存的概念逐渐强化。
fragement 缓存:片段缓存是对应action的,所以如果要跨action调用片段缓存时,需要指定action。
如在controller A,action one的response html中要调用controller B, action two的片段缓存
<% cache(action: 'two', controller: 'B', action_suffix: 'namespace') do %>
Thing.all
<% end%>
其中,action_suffic是在一个response html中存在多个cache时用以区分的namespace。
cache的key又两种指定方式:1. cache(Model_instance)
生成的key格式为Model/instance_id-updated_at
;2.使用helper method自己生成。
片段缓存也嵌套使用,形成俄罗斯套娃(Russian Doll Caching)的特殊形式。
片段缓存的过期方式:expire_fragment(controller: 'A', action: 'one', action_suffix: 'namespace')
- browser端的缓存支持
http协议中包含了ETag、If-None-Match 和 If-Modified-Since之类的header,主要是为了方便实现browser的get请求的缓存使用。
如
class SomeController < ApplicationController
def show
@thing = Thing.find(params[:id])
if stale?(@thing)
respond_to do |format|
.......
end
end
end
end
其中stale?(@thing)
和 stale?(last_modified: @thing.updated_at.utc, etag: @thing.cache_key)
等价。
如果没有respond_to
的复杂逻辑,也可以直接使用fresh_when @thing
以上是我所知道的rails中cache的基本内容。
网友评论