Skip Navigation
Show nav
Dev Center
  • Get Started
  • ドキュメント
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • ドキュメント
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
View categories

Categories

  • Heroku のアーキテクチャ
    • Dyno (アプリコンテナ)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • スタック (オペレーティングシステムイメージ)
    • ネットワーキングと DNS
    • プラットフォームポリシー
    • プラットフォームの原則
  • Developer Tools
    • コマンドライン
    • Heroku VS Code Extension
  • デプロイ
    • Git を使用したデプロイ
    • Docker によるデプロイ
    • デプロイ統合
  • 継続的デリバリーとインテグレーション
    • 継続的統合
  • 言語サポート
    • Node.js
      • Working with Node.js
      • Node.js Behavior in Heroku
      • Troubleshooting Node.js Apps
    • Ruby
      • Rails のサポート
      • Bundler の使用
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Python でのバックグランドジョブ
      • Python Behavior in Heroku
      • Django の使用
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Maven の使用
      • Spring Boot の使用
      • Troubleshooting Java Apps
    • PHP
      • PHP Behavior in Heroku
      • Working with PHP
    • Go
      • Go の依存関係管理
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • データベースとデータ管理
    • Heroku Postgres
      • Postgres の基礎
      • Postgres スターターガイド
      • Postgres のパフォーマンス
      • Postgres のデータ転送と保持
      • Postgres の可用性
      • Postgres の特別なトピック
      • Migrating to Heroku Postgres
    • Heroku Data For Redis
    • Apache Kafka on Heroku
    • その他のデータストア
  • AI
    • Working with AI
    • Heroku Inference
      • Inference API
      • Quick Start Guides
      • AI Models
      • Inference Essentials
    • Vector Database
    • Model Context Protocol
  • モニタリングとメトリクス
    • ログ記録
  • アプリのパフォーマンス
  • アドオン
    • すべてのアドオン
  • 共同作業
  • セキュリティ
    • アプリのセキュリティ
    • ID と認証
      • シングルサインオン (SSO)
    • Private Space
      • インフラストラクチャネットワーキング
    • コンプライアンス
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Team
    • Heroku Connect (Salesforce 同期)
      • Heroku Connect の管理
      • Heroku Connect のリファレンス
      • Heroku Connect のトラブルシューティング
  • パターンとベストプラクティス
  • Heroku の拡張
    • Platform API
    • アプリの Webhook
    • Heroku Labs
    • アドオンのビルド
      • アドオン開発のタスク
      • アドオン API
      • アドオンのガイドラインと要件
    • CLI プラグインのビルド
    • 開発ビルドパック
    • Dev Center
  • アカウントと請求
  • トラブルシューティングとサポート
  • Salesforce とのインテグレーション
  • 言語サポート
  • Ruby
  • Rails のサポート
  • Rails 3.1 以降 (Rails 4 を含む) での Rack::Cache と Memcached の使用

This article was contributed by The MemCachier Add-on

MemCachier manages and scales clusters of memcache servers so you can focus on your app. Tell us how much memory you need and get started for free instantly. Add capacity later as you need it.

follow @MemCachier on Twitter

Rails 3.1 以降 (Rails 4 を含む) での Rack::Cache と Memcached の使用

日本語 — Switch to English

この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。

最終更新日 2021年10月05日(火)

Table of Contents

  • Rack を理解する
  • Rack::Cache
  • Rack::Cache ストレージ
  • Memcached のローカルインストール
  • Rails キャッシュストアと Rack::Cache
  • Rails キャッシュストアの設定
  • Rack::Cache の設定
  • 複数の dyno の処理
  • 静的アセットの供給
  • MemCachier アドオンのプロビジョニング
  • 本番環境でのキャッシング
  • デバッグ

Heroku では、アクセス時のエクスペリエンスを最適化するために、Rack::Cache​ 経由で CDN を使用してアセットの配信を高速化する​ことを推奨しています。すでに CDN を使用している場合、Rack::Cache​ を追加してもアセットの配信は高速化されません。

Cedar スタック​上でアセットを効率的に供給するために、Ruby on Rails アプリケーションで Rack::Cache​ を使用することが推奨されています。Rack::Cache を適切に使用すれば、応答時間が短縮され、負荷が軽減されます。これは、アプリケーションを通じて静的アセットを提供する場合に重要です。

この記事では、Rack::Cache を使用したアセットのキャッシングの概念を要約します。また、Rails 3.1 以降のアプリケーションとアセットパイプラインの適切な設定について説明します。このガイドの内容は Rails 4 アプリケーションにも完全に適用されます。

構築済みの小規模なサンプルアプリの動作は こちら​で確認できます。
​ソースコード​または Heroku にデプロイ

Rack を理解する

Rack​ は、Ruby をサポートする Web サーバーと、Ruby フレームワークの間を取り持つ最小限のインターフェースです。その目的は共通のインターフェースとして機能することであり、これによって Web サーバーでは、Rack を実装するだけで、同じく Rack をサポートする任意の Ruby Web フレームワークをサポートできるようになり、その逆も同様です。

この設計から生まれる優れた機能は、いわゆる “ミドルウェア” です。ミドルウェアは単に、両側で Rack インターフェースを実装するアプリケーションです。つまり、Rack インターフェースを通じて Web サーバーからのリクエストを消費し、何らかの処理を行った後、Rack インターフェースを通じて別のアプリケーションにリクエストを渡します。実際に、Rack インターフェースを使用すれば、Web サーバーとアプリケーションの間に、透過的なプロキシのようなサービスをいくつでも配置できます。 受信 HTTP リクエストの場合、各ミドルウェアは何らかのアクションを実行してから、"ラック" 内の次のミドルウェアにリクエストを渡します。 最終的に、リクエストは正しくフォーマットされてアプリケーションに到達します。

Rack は軽量性と柔軟性を備えるように記述されています。ミドルウェアは、リクエストに直接応答できる場合、Rails アプリケーションとやり取りする必要はありません。これにより、リクエストの戻りが高速化され、Rails アプリケーションの全体的な負荷が軽減されます。

Rails 3 以降や Sinatra を含む多くの Ruby Web フレームワークは Rack を基盤としています。

Rack::Cache

Rack ミドルウェアの Rack::Cache​ によって、アプリケーションでの HTTP キャッシングが実現します。また、アプリケーションにおいて、メインの Rails アプリケーションからの処理を必要とせずにストレージバックエンドからアセットを供給できるようになります。

Rack::Cache ストレージ

Rack::Cache には、メタストアとエンティティストアの 2 種類のストレージ領域があります。 MetaStore は、HTTP リクエストおよび応答のヘッダーなど、個々のキャッシュエントリに関する高レベルの情報を保持します。リクエストが受信されると、キャッシングのコアロジックでは、このメタ情報を使用して、リクエストを満足できる期限内のキャッシュエントリが存在するかどうかを判断します。EntityStore は、実際の応答本体の内容が保存される場所です。応答がキャッシュに入力されると、応答本体の内容の SHA1 ダイジェストが計算され、キーとして使用されます。

Rack::Cache では、MetaStore と EntityStore は区別されるため、それぞれに使用するストレージエンジンをユーザーが個別にカスタマイズできます。MetaStore はアクセス頻度が非常に高い反面、メモリはほとんど必要としません。一方で、EntityStore はアクセス頻度が低く、必要なメモリは多くなります。

Rack::Cache には、file​、heap​、memcache​ の 3 種類のストレージエンジンが付属します。file​ エンジンでのデータ保存は低速ですが、メモリ効率に優れています。heap​ を使用すると、プロセスのメモリが使用されて高速化しますが、際限なく肥大するとパフォーマンスに影響が出る可能性があります。memcache​ の使用は最速のオプションですが、大きなオブジェクトの保存には適していません。

エンティティストアとメタストアの詳細は、Rack キャッシュストレージ​に関する記事を参照してください。

MetaStore と memcache​ ストレージエンジンを使用すると、共有メタデータへの非常に高速なアクセスが可能になります。一方で、EntityStore の file​ エンジンを使用すれば、オブジェクトのサイズが大きくなり、アプリケーションパフォーマンスプロファイルが効率的で予測可能になるため、Heroku ではこちらを推奨しています。

Memcached のローカルインストール

他の OS でのローカルインストール手順については、MemCachier アドオンの記事​をご覧ください。

アプリケーションをローカルで実行して Rack::Cache の設定をテストするには、memcached がインストールされている必要があります。Mac OSX では、homebrew などのツールを使用してインストールできます。

$ brew install memcached

インストールが終了すると、memcached を手動で起動する方法と、システム起動時に自動起動する方法について homebrew から指示があります。

Rails キャッシュストアと Rack::Cache

Rails には、Rack::Cache とは別に、独自の組み込みのキャッシングシステムが備わっています。 このシステムは一般に、Rack::Cache とは異なる目的に使用されます。

Rails キャッシングシステムは、コントローラーアクションとページフラグメントをキャッシュするためのものですが、Rails コードは呼び出します。 一方、Rack::Cache は、スタイルシート、JavaScript、画像などの完全に静的なアセットのキャッシングを管理します。キャッシュヒットによって Rails コードが呼び出されることはありません。 Rack::Cache は Varnish、Nginx、Apache などの CDN または HTTP キャッシュを代替しますが、Rails キャッシングシステムはこれらから完全に独立しています。

Rails キャッシングシステムの詳細は、こちら​をご覧ください。 Memcache も有力な選択肢であり、このシステムでの使用が十分にサポートされています。

Rails キャッシュストアの設定

この手順では、memcached を使用するように Rails キャッシングシステムを設定します。Rails キャッシングシステムは Rack::Cache から独立しているため、これは厳密に必須というわけではありません。しかし、キャッシングシステムを統合することが推奨されています。

Rack::Cache gem と、推奨の memcached クライアントである Dalli​ をインストールする必要があります。Gemfile​ で、次の内容を追加します。

gem 'rack-cache'
gem 'dalli'

オプションですが、より高速な kgio IO システムをインストールすることもお勧めします。

gem 'kgio'

bundle install​ を実行して Dalli をアプリケーションの依存関係として確立した後、そのキャッシュストアに Dalli クライアントを使用するよう、config/application.rb​ で Rails に指示します。

config.cache_store = :mem_cache_store

ローカルの Rails コンソールセッションを開始し、単純なキーと値を取得および設定することによって、設定を確認します。

$ rails c
> mc = Dalli::Client.new
> mc.set('foo', 'bar')
> mc.get('foo')
'bar'

memcached を使用するようにアプリケーションを設定したら、次は Rack::Cache を設定します。

Rack::Cache の設定

config/environments/production.rb​ 環境ファイルに変更を加えて、Rails の組み込み Rack::Cache 統合に適したストレージバックエンドを指定します。

指定しない場合、Dalli::Client.new​ は memcache サーバーの場所を自動的に MEMCACHE_SERVERS​ 環境変数から取得します。存在しない場合、 デフォルトで localhost とデフォルトポート (11211) になります。

client = Dalli::Client.new((ENV["MEMCACHIER_SERVERS"] || "").split(","),
                           :username => ENV["MEMCACHIER_USERNAME"],
                           :password => ENV["MEMCACHIER_PASSWORD"],
                           :failover => true,
                           :socket_timeout => 1.5,
                           :socket_failure_delay => 0.2,
                           :value_max_bytes => 10485760)
config.action_dispatch.rack_cache = {
  :metastore    => client,
  :entitystore  => client
}
config.static_cache_control = "public, max-age=2592000"

設定オプションの完全なリストはこちら​で確認できますが、上記のもので十分です。

:value_max_bytes​ オプションは 10 MB に設定します。このようにしないと、1 MB より大きいアセットに対して Rack::Cache が HTTP 5xx エラー応答を返します。その原因は、memcached ではデフォルトで 1 MB 以下の値しか許可されず、1 MB より大きいキーと値のペアを set​ しようとすると Dalli で例外がスローされるためです。:value_max_bytes​ を 10 MB に増やすと、Dalli でこのエラーがスローされなくなる代わりに、memcache サーバーは 1 MB を超えるアセットについてミスを返すようになります。したがって、非常に大きいアセットは Rack::Cache によって供給されない (もっとも、これらの種類のアセットにとっては特にメリットがない) ものの、これによって問題が起きることはありません。

複数の dyno の処理

EntityStorage には file​ ストレージエンジンを使用することをお勧めしますが、複数の dyno を使用する場合、Heroku ではこれは不可能です。問題は、MetaStore に memcache​ を使用する場合、どのファイルが現在キャッシュされていないか、またはキャッシュされているかに関するすべてのメタデータがすべての dyno 間で共有されることです。ただし、file​ ストアはそうではなく、dyno ローカルに限定されます。したがって、ファイルをキャッシュする最初の dyno はそのローカルディスクにファイルを保存しますが、キャッシュにファイルが含まれていることを他のすべての dyno に通知します。他の dyno では、それぞれのキャッシュに実際のファイルが存在しないため、キャッシュからファイルが見つかることもありません。

ここでは、EntityStore にも memcached を使用するアプローチを採用します。もう 1 つの選択肢は、dyno 固有のプレフィックスを MetaStore のキーに使用するように各 dyno を設定し、各 dyno の Rack::Cache の独立性を保つというものです。

あるいは、memcached を完全に排除して、MetaStore には heap​ ストアを、EntityStore には file​ ストアをそれぞれ使用することもできます。

静的アセットの供給

GitHub のリファレンスアプリケーション​の production.rb​ 設定を参照してください。

アプリケーションで静的アセットを適切に供給、無効化、更新できるようにするには、config/environments/production.rb​ でいくつかの設定を更新する必要があります。Rails にアセットを供給させる (したがって、Rack::Cache によって管理されるようにする) には、serve_static_assets​ 設定を 使用します。

config.serve_static_assets = true

加えて、Cache-Control ヘッダーを設定することによって、アイテムがキャッシュにとどまる時間の長さを指定します。Cache-Control ヘッダーがない場合、静的ファイルは Rack::Cache によって保存されません。

config.static_cache_control = "public, max-age=2592000"

これらの設定は、静的要素をかなり長時間保存するよう Rack::Cache に指示します。

Cache-Control​ ヘッダーと HTTP キャッシング​ は、通常、動的コンテンツにも適用できます。

変更が加えられたファイルを正しく無効化するために、Rails では、各ファイルのハッシュダイジェストを保持し、計算されたファイル名の一部としてそれを保存します。これがファイルのフィンガープリントの役割を果たすので、ファイルが変更されたときの検出が可能になります。 config.assets.digest​ 設定でこのアプローチを有効にします。

config.assets.digest = true

本番環境でキャッシュが有効になっていることを確認する必要もあります。

config.action_controller.perform_caching = true

MemCachier アドオンのプロビジョニング

Rack::Cache の MetaStore として memcache を使用するので、MemCachier アドオン を Heroku 上のアプリケーションに追加する必要があります。

$ heroku addons:create memcachier:dev
----> Adding memcachier on memcachier-direct... done, v24 (free)

MemCachier が設定する環境変数のプレフィックスは MEMCACHIER​ です (MEMCACHE​ ではありません)。ただしこれは、memcachier​ gem によって自動的に修正されます。これを gemfile に含めます。

gem "memcachier"

本番環境でのキャッシング

アプリケーションを Heroku にデプロイし、heroku logs​ コマンドを使用してキャッシュ出力を表示します。

$ git push heroku master
$ heroku logs --ps web -t

ハードリフレッシュを使用すると、ブラウザのキャッシュがクリアされて アセットの強制的なリクエストに役立ちます。ほとんどのブラウザでは、Shift-R​ ショートカットでハードリフレッシュを実行します。

本番環境のログストリームに cache​ エントリが出現します。miss, store​ トークンは、項目がキャッシュに見つからなかったが次のリクエストのために保存されたことを示します。

cache: [GET /assets/application-95bd4fe1de99c1cd91ec8e6f348a44bd.css] miss, store
cache: [GET /assets/application-95fca227f3857c8ac9e7ba4ffed80386.js] miss, store
cache: [GET /assets/rails-782b548cc1ba7f898cdad2d9eb8420d2.png] miss, store

fresh​ は、項目がキャッシュに見つかってそこから取得されたことを示します。

cache: [GET /assets/application-95bd4fe1de99c1cd91ec8e6f348a44bd.css] fresh
cache: [GET /assets/application-95fca227f3857c8ac9e7ba4ffed80386.js] fresh
cache: [GET /assets/rails-782b548cc1ba7f898cdad2d9eb8420d2.png] fresh

これで完了です。Rails 3.1 以降のアプリケーションは、memcached を使用して静的アセットをキャッシュするように設定されたので、その役割から解放された dyno で動的なアプリケーションリクエストを実行できるようになります。

デバッグ

設定が正しくない場合、store​ または fresh​ の代わりに miss​ がログに記録されることがあります。

cache: [GET /assets/application-95bd4fe1de99c1cd91ec8e6f348a44bd.css] miss
cache: [GET /assets/application-95fca227f3857c8ac9e7ba4ffed80386.js] miss
cache: [GET /assets/rails-782b548cc1ba7f898cdad2d9eb8420d2.png] miss

その場合は、curl​ を使用してアセット応答ヘッダーを検査し、Cache-Control ヘッダーが存在していることを確認してください。

$ curl -I 'http://memcachier-examples-rack.herokuapp.com/assets/shipit-72351bb81da0eca408d9bd8342f1b972.jpg'
HTTP/1.1 200 OK
Age: 632
Cache-Control: public, max-age=2592000
Content-length: 70522
Etag: "72351bb81da0eca408d9bd8342f1b972"
Last-Modified: Sun, 25 Mar 2012 01:51:21 GMT
X-Rack-Cache: fresh

応答ヘッダーに Cache-Control​ が含まれ、その値が config.static_cache_control​ 設定の具体的な値 (public, max-age=2592000) である必要があります。X-Rack-Cache ヘッダーがアセットの状態 (fresh/store/miss) を示していることも確認してください。. Also confirm that you are seeing the​予期しない結果になった場合は、本番環境の設定を確認してください。

ファイルバージョンの不整合

ファイルに変更を加えてもサーバーから古いファイルが供給され続ける場合は、デプロイする前に、ファイルを Git リポジトリにコミットしたことを確認してください。 heroku run bash​ を使用して public/assets​ ディレクトリの内容を一覧表示すると、コンパイルされたコードにそのファイルが存在するかどうかを 確認できます。ハッシュ化されたアセットファイル名がこのディレクトリに含まれているはずです。

$ heroku run bash
Running bash attached to terminal... up, run.1
$ ls public/assets
application-95bd4fe1de99c1cd91ec8e6f348a44bd.css      application.css           manifest.yml
application-95bd4fe1de99c1cd91ec8e6f348a44bd.css.gz   application.css.gz        rails-782b548cc1ba7f898cdad2d9eb8420d2.png
application-95fca227f3857c8ac9e7ba4ffed80386.js       application.js            rails.png
application-95fca227f3857c8ac9e7ba4ffed80386.js.gz    application.js.gz

Rails の manifest.yml​ にそのファイルの記述があることも確認してください。

$ cat public/assets/manifest.yml
rails.png: rails-782b548cc1ba7f898cdad2d9eb8420d2.png
application.js: application-95fca227f3857c8ac9e7ba4ffed80386.js
application.css: application-95bd4fe1de99c1cd91ec8e6f348a44bd.css

探しているファイルが見つからない場合は、bundle exec rake assets:precompile RAILS_ENV=production をローカルで実行して、当該のファイルがご自身の public/assets​ ディレクトリにあることを確認してください。

関連カテゴリー

  • Rails のサポート
Unicorn を使用した Rails アプリケーションのデプロイ Rails アプリケーションを Puma Web サーバーでデプロイする

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices