ステータス:非推奨

この記事では、サポートされなくなったバージョンのUbuntuについて説明します。 現在Ubuntu12.04を実行しているサーバーを運用している場合は、サポートされているバージョンのUbuntuにアップグレードまたは移行することを強くお勧めします。

理由:
Ubuntu 12.04は2017年4月28日に保守終了(EOL)に達しました and no longer receives security patches or updates. This guide is no longer maintained.

代わりに参照してください:
このガイドは参照として役立つ場合がありますが、他のUbuntuリリースでは機能しない場合があります。 可能な場合は、使用しているUbuntuのバージョン用に作成されたガイドを使用することを強くお勧めします。 ページ上部の検索機能を使用して、より新しいバージョンを見つけることができます。

序章

Memcachedは、非常に高速なメモリ内オブジェクトキャッシングシステムであり、わずかな変更でRailsをはるかに高速に実行できます。

前提条件:

このチュートリアルは、RubyonRailsとMemcachedがすでにインストールされていることを前提としています。 そうでない場合、チュートリアルは以下にリンクされています。

また、Railsアプリケーションが稼働していて、Memcachedを使用して最適化する準備ができていることも前提としています。

DalliGemをインストールします

最初に行う必要があるのは、MikePerham’のDalliGemをインストールすることです。

gem install dalli

Bundlerを使用する場合は、gem 'dalli'をGemfileに追加し、bundle installを実行します。

これは、Memcachedと対話するための超高速で機能満載の方法になります。

Railsを構成する

memcachedを使用するようにRailsを構成するための最初のステップは、config/environments/production.rbを編集し、次の行を追加して、RailsにDalliを使用するように指示することです。

config.cache_store = :dalli_store

次に、アクションコントローラーにキャッシングを実行するように指示します。 この行を同じファイルに追加します。

config.action_controller.perform_caching = true

次に、通常どおりにRailsアプリケーションを再起動します。

Railsアプリケーションを変更する

先ほど行った変更を利用するには、Railsアプリケーションを更新する必要があります。 memcachedが提供するスピードアップを利用するには、主に2つの方法があります。

キャッシュ制御ヘッダーを追加する

memcachedを利用する最も簡単な方法は、アクションの1つにCache-Controlヘッダーを追加することです。 これにより、Rack::Cacheはそのアクションの結果をmemcachedに保存します。 app/controllers/slow_controller.rbで次のアクションが発生した場合:

def slow_action
  sleep 15
  # todo - print something here
end

次の行を追加して、Rack::Cacheに結果を5分間保存するように指示できます。

def slow_action
  expires_in 5.minutes
  sleep 15
  # todo - print something here
end

これで、このアクションを2回実行すると、大幅に高速化されていることがわかります。 Railsは、Rack :: Cacheを更新するために、5分ごとに1回実行するだけで済みます。

これにより、Cache-Controlヘッダーがパブリックに設定されることに注意してください。 1人のユーザーだけが表示する必要がある特定のアクションがある場合は、expires_in 5.minutes, :public => falseを使用してください。 また、応答をキャッシュする適切な時間を決定する必要があります。これはアプリケーションごとに異なります。

HTTPキャッシングの詳細については、MarkNottingham’のWeb作成者およびWebマスター向けのキャッシングチュートリアルを参照してください。

オブジェクトをMemcachedに保存する

毎回作成する必要のある非常にコストのかかる操作やオブジェクトがある場合は、memcachedに保存して取得できます。 あなたの行動が次のようになっているとしましょう:

def slow_action
  slow_object = create_slow_object
end

次のようにアクションを変更することで、結果をmemcachedに保存できます。

def slow_action
  slow_object = Rails.cache.fetch(:slow_object) do 
      create_slow_object
  end
end

Railsはmemcachedに「slow_object」のキーを持つオブジェクトを要求します。 そのオブジェクトが見つからない場合は、指定されたブロックを実行し、オブジェクトをそのオブジェクトに書き戻します。

フラグメントキャッシング

フラグメントキャッシングは、アプリケーションのどの部分が最も動的であり、最適化する必要があるかを選択できるRailsの機能です。 ビューの周囲の任意の部分をcacheブロックに簡単にキャッシュできます。

<% # app/views/managers/index.html.erb  %>
<% cache manager do %>
  Manager's Direct Reports:
  <%= render manager.employees %>
<% end %> 

<% # app/views/employees/_employee.html.erb %>
<% cache employee do %>
    Employee Name: <%= employee.name %>
    <%= render employee.incomplete_tasks %>
<% end %>

<% # app/views/tasks/_incomplete_tasks.html.erb %>
<% cache task do %>
    Task: <%= task.title %>
    Due Date: <%= task.due_date %>
<% end %>

上記の手法は、伝統的なロシアの入れ子人形をほのめかすロシア人形キャッシングと呼ばれます。 次に、Railsはこれらのフラグメントをmemcachedにキャッシュし、モデルをcacheステートメントに追加したため、このキャッシュオブジェクト’のキーはオブジェクトが変更されると変更されます。 ただし、これによって発生する問題は、タスクが更新されるときです。

@todo.completed!
@todo.save!

キャッシュオブジェクトをキャッシュオブジェクト内にネストしているため、Railsはこのモデルに依存するキャッシュフラグメントを期限切れにすることを認識しません。 ここで、ActiveRecordtouchキーワードが役に立ちます。

class Employee < ActiveRecord::Base
  belongs_to :manager, touch: true
end

class Todo < ActiveRecord::Base
  belongs_to :employee, touch: true
end

これで、Todoモデルが更新されると、キャッシュフラグメントが期限切れになり、Employeeモデルにもフラグメントも更新する必要があることが通知されます。 次に、EmployeeフラグメントがManagerモデルに通知し、この後、キャッシュの有効期限プロセスが完了します。

ロシア人形のキャッシングが私たちにもたらすもう1つの問題があります。 新しいアプリケーションをデプロイするとき、Railsはビューテンプレートが変更されたことをいつチェックするかを知りません。 タスクリストビューを部分的に更新すると、次のようになります。

<% # app/views/tasks/_incomplete_tasks.html.erb %>
<% cache task do %>
    Task: <%= task.title %>
    Due Date: <%= task.due_date %>
    <p><%= task.notes %></p>
<% end %>

Railsは、ビューパーシャルを使用するキャッシュフラグメントを期限切れにしません。 以前はcacheステートメントにバージョン番号を追加する必要がありましたが、現在は cache_digests というgemがあり、テンプレートファイルのMD5ハッシュをキャッシュキーに自動的に追加します。 パーシャルを更新してアプリケーションを再起動すると、ビューテンプレートファイルのMD5が変更され、Railsがそのテンプレートを再度レンダリングするため、キャッシュキーは一致しなくなります。 また、テンプレートファイル間の依存関係も処理するため、上記の例では、_incomplete_tasks.html.erbが更新されると、依存関係チェーンの上位にあるすべてのキャッシュオブジェクトが期限切れになります。

この機能は、Railsバージョン4.0に自動的に含まれています。 Rails 3プロジェクトでこのgemを使用するには、次のコマンドを入力します。

gem install cache_digests

または、Bundlerを使用する場合は、次の行をGemfileに追加します。

gem 'cache_digests'

高度なレールとMemcachedセットアップ

Dalli Ruby Gemは非常に強力で、memcachedサーバーのクラスター全体にキーを分散する処理を行います。これにより、負荷が分散され、memcachedの容量が増加します。 Web層に複数のWebサーバーがある場合は、それらの各サーバーにmemcachedをインストールして、それらすべてをconfig/environments/production.rbに追加できます。

config.cache_store = :dalli_store, 'web1.example.com', 'web2.example.com', 'web3.example.com'

これは、コンシステントハッシュを使用して、使用可能なmemcachedサーバー全体にキーを分散します。

投稿者:Andrew Williams