首先給大家看一下 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>
新聞熱點
疑難解答