Analyze the application of Cache in Ruby China

Source: Internet
Author: User
Tags mongodb query

First, let's take a look at the NewRelic report.

Average response time of the last 24 h

Pages with high traffic)

Several actions of traffic volume:

TopicsController # show

UsersController # show (miserable, mainly because GitHub API requests are slowed down)

PS: before publishing this article, I made a slight modification. The GitHub request is put into the backend queue for processing. The new result is as follows:

TopicsController # index

HomeController # index

From the preceding report, the response time for Ruby China back-end requests beyond the user homepage is within 100 ms, or even lower.

How do we do this?

Markdown Cache
Fragment Cache
Data Cache
ETag
Static resource cache (JS, CSS, images)
Markdown Cache

When the content is modified, the Markdown result is saved to the database to avoid repeated computation during browsing.

In addition, this item is not specifically put into the Cache, but in the database:

In order to ensure persistence, Memcached can be stopped and lost in large quantities;
Avoid occupying too much cache memory;

Class Topic field: body # stores the original content, which is used to modify field: body_html # stores the calculated results and displays before_save: markdown_body def markdown_body self. body_html = MarkdownTopicConverter. format (self. body) if self. body_changed? EndendFragment Cache

This is the most widely used cache solution in Ruby China, and it is also the reason for the speed improvement.

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 ") %>... content omitted </div> <% end %>

Use the cache_key of the topic as the cache views/topics/{number}-# {Update time}/{suggest parameter}/{file content MD5}-> views/topics/19105-20140508153844 /false/bc178d556ecaee49971b0e80b3566f12
For some scenarios where different statuses are displayed based on the user account, you can directly prepare the complete HTML file and control the status through JS, such as the current "like" function.

<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>

For example

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 => "Modify reply") %> <% = link_to ("", "#", 'Data-pload' => 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> <% end %>

Also, the cache_key of reply is used to cache views/replies/202695-20140508081517/raw: false/d91dddbcb269f3e0172bf5d0d27e9088.

At the same time, complicated user permission control is implemented using 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>

Data Cache

In fact, most Model queries in Ruby China are not cached, because according to the actual situation, the MongoDB query response time is very fast, and most of the scenarios are within 5 ms, or even lower.

We will make some data query caches for price comparison, such as: 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 is a parameter that can be included in the HTTP Request and Response. It is used to check whether the content has been updated to reduce network overhead.

This is probably the process.

The fresh_when method of Rails can help generate ETag information for your query content.

def show @topic = Topic.find(params[:id]) fresh_when(etag: [@topic])end

Static resource Cache

Please do not underestimate this, the back-end writing is faster, it may also be slowed down (the performance on the browser )!

1. make proper use of Rails Assets Pipeline. You must enable it!

# config/environments/production.rbconfig.assets.digest = true

2. Set the cache Validity Period of CSS, JS, and Image to max in Nginx;

location ~ (/assets|/favicon.ico|/*.txt) { access_log    off; expires      max; gzip_static on;}

3. Reduce the number of JS, CSS, and Image pages as much as possible. The simple method is to merge them to reduce the HTTP request overhead;

<Head>... there are only two <link href = "// users" rel = "stylesheet"/> <script src = "// users"> </script>... 

Some Tips

View statistics logs to prioritize pages with high traffic;
Updated_at is something that helps you clear the cache and make good use of it! Do not ignore data modification!
Pay more attention to the query time in your Rails Log. The page response time of 100 ms is a good status, and users who exceed 200 ms will feel dull.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.