分析Cache 在 Ruby China 裡面的應用情況_ruby專題

來源:互聯網
上載者:User

首先給大家看一下 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? endendFragment Cache

這個是 Ruby China 裡面用得最多的緩衝方案,也是速度提升的原因所在。

app/views/topics/_topic.html.erb<% cache([topic, suggest]) do %><div class="topic topic_line topic_<%= topic.id %>">  <%= link_to(topic.replies_count,"#{topic_path(topic)}#reply#{topic.replies_count}",     :class => "count state_false") %> ... 省略內容部分</div><% end %>

用 topic 的 cache_key 作為緩衝 cache views/topics/{編號}-#{更新時間}/{suggest 參數}/{檔案內容 MD5} -> views/topics/19105-20140508153844/false/bc178d556ecaee49971b0e80b3566f12
某些涉及到根據使用者帳號,有不同狀態顯示的地方,直接把完整 HTML 準備好,通過 JS 控制狀態,比如目前的“喜歡“功能。

<script type="text/javascript"> var readed_topic_ids = <%= current_user.filter_readed_topics(@topics) %>; for (var i = 0; i < readed_topic_ids.length; i++) {  topic_id = readed_topic_ids[i];  $(".topic_"+ topic_id + " .right_info .count").addClass("state_true"); }</script>

再比如

app/views/topics/_reply.html.erb <% cache([reply,"raw:#{@show_raw}"]) do %><div class="reply"> <div class="pull-left face"><%= user_avatar_tag(reply.user, :normal) %></div> <div class="infos">  <div class="info">   <span class="name">    <%= user_name_tag(reply.user) %>   </span>   <span class="opts">    <%= likeable_tag(reply, :cache => true) %>    <%= link_to("", edit_topic_reply_path(@topic,reply), :class => "edit icon small_edit", 'data-uid' => reply.user_id, :title => "修改回帖")%>    <%= link_to("", "#", 'data-floor' => floor, 'data-login' => reply.user_login,      :title => t("topics.reply_this_floor"), :class => "icon small_reply" )    %>   </span>  </div>  <div class="body">   <%= sanitize_reply reply.body_html %>  </div> </div></div><% end %>

同樣也是通過 reply 的 cache_key 來緩衝 views/replies/202695-20140508081517/raw:false/d91dddbcb269f3e0172bf5d0d27e9088

同時這裡還有複雜的使用者權限控制,用 JS 實現;

<script type="text/javascript"> $(document).ready(function(){  <% if admin? %>   $("#replies .reply a.edit").css('display','inline-block');  <% elsif current_user %>   $("#replies .reply a.edit[data-uid='<%= current_user.id %>']").css('display','inline-block');  <% end %>  <% if current_user && !@user_liked_reply_ids.blank? %>   Topics.checkRepliesLikeStatus([<%= @user_liked_reply_ids.join(",") %>]);  <% end %> })</script>

資料緩衝

其實 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 itemsendETag

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.rbconfig.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 要求開銷;

<head> ...  只有兩個 <link href="//ruby-china-files.b0.upaiyun.com/assets/front-1a909fc4f255c12c1b613b3fe373e527.css" rel="stylesheet" /> <script src="//ruby-china-files.b0.upaiyun.com/assets/app-24d4280cc6fda926e73419c126c71206.js"></script> ...</head>

一些 Tips

看統計日誌,優先處理流量高的頁面;
updated_at 是一個非常有利於協助你清理緩衝的東西,善用它!修改資料的時候別忽略它!
多關注你的 Rails Log 裡面的查詢時間,100ms 一下的頁面回應時間是一個比較好的狀態,超過 200ms 使用者就會感覺到遲鈍了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.