首页 > 编程 > Ruby > 正文

Cache在Ruby China中的应用深度解析

2020-02-24 15:40:12
字体:
来源:转载
供稿:网友

  今天小编给大家分享一篇Cache在Ruby China中的应用深度解析,感兴趣的朋友跟小编一起来了解一下吧!

  首先给大家看一下 NewRelic 的报表

  最近 24h 的平均响应时间

  流量高的那些页面 (Action)

  访问量搞的几个 Action 的情况:

  TopicsController#show

  UsersController#show (比较惨,主要是 GitHub API 请求拖慢)

  PS: 在发布这篇文章之前我有稍加修改了一下,GitHub 请求放到后台队列处理,新的结果是这样:

  TopicsController#index

  HomeController#index

  从上面的报表来看,目前 Ruby China 后端的请求,排除用户主页之外,响应时间都在 100ms 以内,甚至更低。

  我们是如何做到的?

  Markdown 缓存

  Fragment Cache

  数据缓存

  ETag

  静态资源缓存 (JS,CSS,图片)

  Markdown 缓存

  在内容修改的时候就算好 Markdown 的结果,存到数据库,避免浏览的时候反复计算。

  此外这个东西也特意不放到 Cache,而是放到数据库里面:

  为了持久化,避免 Memcached 停掉的时候,大量丢失;

  避免过多占用缓存内存;

  class Topic

  field :body # 存放原始内容,用于修改

  field :body_html # 存放计算好的结果,用于显示

  before_save :markdown_body

  def markdown_body

  self.body_html = MarkdownTopicConverter.format(self.body) if self.body_changed?

  end

  end

  Fragment Cache

  这个是 Ruby China 里面用得最多的缓存方案,也是速度提升的原因所在。

  app/views/topics/_topic.html.erb

  

  

 

  

  :class => "count state_false") %>

  ... 省略内容部分

  

 

  

  用 topic 的 cache_key 作为缓存 cache views/topics/{编号}-#{更新时间}/{suggest 参数}/{文件内容 MD5} -> views/topics/19105-20140508153844/false/bc178d556ecaee49971b0e80b3566f12

  某些涉及到根据用户帐号,有不同状态显示的地方,直接把完整 HTML 准备好,通过 JS 控制状态,比如目前的“喜欢“功能。

  

  var readed_topic_ids = ;

  for (var i = 0; i

  topic_id = readed_topic_ids[i];

  $(".topic_"+ topic_id + " .right_info .count").addClass("state_true");

  }

  

  再比如

  app/views/topics/_reply.html.erb

  

  

 

  

 

 

  

 

  

 

  

  

  

  

   true) %>

   "edit icon small_edit", 'data-uid' => reply.user_id, :title => "修改回帖")%>

   floor, 'data-login' => reply.user_login,

  :title => t("topics.reply_this_floor"), :class => "icon small_reply" )

  %>

  

  

 

  

 

  

  

 

  

 

  

 

  

  同样也是通过 reply 的 cache_key 来缓存 views/replies/202695-20140508081517/raw:false/d91dddbcb269f3e0172bf5d0d27e9088

  同时这里还有复杂的用户权限控制,用 JS 实现;

  

  $(document).ready(function(){

  

  $("#replies .reply a.edit").css('display','inline-block');

  

  $("#replies .reply a.edit[data-uid='']").css('display','inline-block');

  

  

  Topics.checkRepliesLikeStatus([]);

  

  })

  

  数据缓存

  其实 Ruby China 的大多数 Model 查询都没有上 Cache 的,因为据实际状况来看, MongoDB 的查询响应时间都是很快的,大部分场景都是在 5ms 以内,甚至更低。

  我们会做一些比价负责的数据查询缓存,比如:GitHub Repos 获取

  def github_repos(user_id)

  cache_key = "user:#{user_id}:github_repos"

  items = Rails.cache.read(cache_key)

  if items.blank?

  items = real_fetch_from_github()

  Rails.cache.write(cache_key, items, expires_in: 15.days)

  end

  return items

  end

  ETag

  ETag 是在 HTTP Request, Response 可以带上的一个参数,用于检测内容是否有更新过,以减少网络开销。

  过程大概是这样

  Rails 的 fresh_when 方法可以帮助将你的查询内容生成 ETag 信息

  def show

  @topic = Topic.find(params[:id])

  fresh_when(etag: [@topic])

  end

  静态资源缓存

  请不要小看这个东西,后端写得再快,也有可能被这些拖慢(浏览器上面的表现)!

  1、合理利用 Rails Assets Pipeline,一定要开启!

  # config/environments/production.rb

  config.assets.digest = true

  2、在 Nginx 里面将 CSS, JS, Image 的缓存有效期设成 max;

  location ~ (/assets|/favicon.ico|/*.txt) {

  access_log off;

  expires max;

  gzip_static on;

  }

  3、尽可能的减少一个页面 JS, CSS, Image 的数量,简单的方法是合并它们,减少 HTTP 请求开销;

  

  ...

  只有两个

  

  

  ...

  

  一些 Tips

  看统计日志,优先处理流量高的页面;

  updated_at 是一个非常有利于帮助你清理缓存的东西,善用它!修改数据的时候别忽略它!

  多关注你的 Rails Log 里面的查询时间,100ms 一下的页面响应时间是一个比较好的状态,超过 200ms 用户就会感觉到迟钝了。

  以上就是Cache在Ruby China中的应用深度解析,想必都了解了吧,更多相关内容请继续关注武林技术频道。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选