Railsで、簡単に静的コンテンツのみを別サーバから配信する方法

by dave


Webサービスでは、JavaScriptファイルや、スタイルシート(CSS)ファイル、画像ファイルなど、細々とした多くの静的コンテンツ(静的ファイル)を扱う場合が多々あるかと思います。


そんな中、公開しているサービスへのアクセスが少し多くなってきた場合、静的コンテンツの配信サーバを、アプリケーションが稼動しているサーバとは別のものにしたくなりますよね。

また、画面内でアイコン画像を多数扱う場合等、多くの静的コンテンツを配信している場合などは、複数の静的コンテンツ用の配信サーバを準備し、負荷分散させることを考えますし、Amazon EC2など、海外のサーバを利用してサービスを展開する場合、どうしてもネットワークの遅延がネックとなりますので、細かい静的コンテンツの配信のみは、国内のサーバを使ったりしたくなる場合もあるかと思います。


そんなとき、Railsでは簡単に設定1つで切り替えられる仕組みがあるようです。
# Thanks! id:mat_aki

別のサーバ(ドメイン)から静的コンテンツを配信するやり方

Railsアプリケーションだと、静的コンテンツについては通常であれば"${RAILS_ROOT}/public/"以下に配置するかと思いますが、その"${RAILS_ROOT}/public/"を別のサーバ(例: assets.example.jp の document root 以下)に配置した後、


"${RAILS_ROOT}/config/environment.rb"あたりに、

ActionController::Base.asset_host = "assets.example.jp"

と書いておけば、"image_tag"や"javascript_include_tag"、"stylesheet_link_tag"などで生成された静的コンテンツへのリンクには、上記の例ですと"assets.example.jp"が指定されるようになります。
Railsの仕組みを使うことで、簡単に設定することが可能です!

複数のサーバから静的コンテンツを配信するやり方

・・・上記と同様に、

ActionController::Base.asset_host = "assets%d.example.jp"

と書いておくことで、

  • assets0.example.jp
  • assets1.example.jp
  • assets2.example.jp
  • assets3.example.jp

の4つのサーバのどれかをランダムに割り振ってくれるようになり負荷分散させることも可能です。(Rails2.0以降で有効かも)
冗長性の話については後述しますが、ものすごく簡単に設定することができます。
ただし、複数のサーバに同じコンテンツを配置しておくことが前提となります。うまくツールを使ってデプロイしましょう。


また、

ActionController::Base.asset_host = Proc.new { |source| "http://assets#{rand(2) + 1}.example.jp" }

と書いておけば、

  • assets1.example.jp
  • assets2.example.jp

の2サーバから配信されるよう、リンクが生成されます。
こんな感じで柔軟に設定することもできそうです。


ただし上記で紹介した設定の場合、指定された先のサーバがダウンした場合も、ダウンしたサーバが割り振られ続けることになるため、複数の静的コンテンツ配信サーバを使いつつ、冗長性・可用性を高めるためには、静的コンテンツ配信サーバのフロントにロードバランサを入れるか、DNSラウンドロビンを使うことを推奨します。

※ DNSラウンドロビンもブラウザ仕様に依存しますが、DNSサーバから返されたIPアドレスのリストから、アクセスに成功するまで順にアクセスするため、簡易な負荷分散・高可用性な仕組みに貢献できます。割り振りの重み付けは不可ですが・・・。

ファイルの種類によって、配信サーバを使い分けるやり方

指定されたURLのパスによって、配信元のサーバを変えることも可能です。
例えば、、、

ActionController::Base.asset_host = Proc.new { |source|
  if source.starts_with?('/images')
    "http://images.example.jp"
  elsif source.starts_with?('/custom')
    ""
  else
    "http://assets.example.jp"
  end
}

↑の設定例ですと、"/images"以下へのアクセスは"images.example.jp"から配信、"custom"以下へのアクセスは自サーバから配信、それ以外の静的コンテンツは"assets.example.jp"から配信されるようになります。
配信元のサーバをファイルの種類などによって使い分けたい場合などに有効です。

参考


実践 Rails ―強力なWebアプリケーションをすばやく構築するテクニック

実践 Rails ―強力なWebアプリケーションをすばやく構築するテクニック