AWS CloudFront経由で静的コンテンツを配信する
画像、音声、css、jsなど静的コンテンツをAWS CloudFront経由で配信してwebサーバの負荷を軽減するようにします。 CloudFrontはリバースプロキシ型のキャッシュサーバのように動作します。
CloudFrontを試していたところ一つ問題を確認しています。クライアント端末がgoogleのパブリックDNSを使っている場合だと、CloudFrontからのリソース読み込みが遅くなる可能性があります。(参考になる記事) 今のところサーバサイドで解決する方法はわかっていません。2014-4-14:AWSのほうで対応したようです
構成
動的コンテンツと静的コンテンツのURLのドメインをあらかじめ分けておいて、静的コンテンツのリクエストはCloudFrontのほうに届くようにしておきます。静的コンテンツ配信のドメインをimage.staging.example.comとします。
端末 | リクエスト http://image.staging.example.com/assets/xxxx | CloudFront [image.staging.example.com] | キャッシュがCloudFrontになければ、下のoriginからリソースを取得してきて端末に配信する | (キャッシュできるものであればキャッシュする) | web server(origin) [origin.staging.example.com] | CloudFrontからのリクエストに応じてリソースを配信する | app server
アプリがRails製なのでasset_hostで指定します。
- config/environments/staging.rb
config.action_controller.asset_host = "image.staging.example.com"
CloudFrontディストリビューションの作成
スクリプトで作成できるようにしておきます。
- CloudFront配信のドメイン - image.staging.example.com
- オリジンサーバのドメイン - origin.staging.example.com
stage = ARGV.shift stage ||= "staging" asset_host = "image.#{stage}.example.com" origin_host = "origin.#{stage}.example.com" cf = AWS::CloudFront.new cf.client.create_distribution({ :distribution_config => { :caller_reference => Time.now.to_i.to_s, :aliases => {:items => [asset_host], :quantity => 1}, :default_root_object => "index", :origins => { :items => [{ :id=>"Custom-#{origin_host}", :domain_name => origin_host, :custom_origin_config => { :http_port => 80, :https_port => 443, :origin_protocol_policy => "http-only" } }], :quantity => 1 }, :default_cache_behavior => { :target_origin_id => "Custom-#{origin_host}", :forwarded_values => { :query_string => false, :cookies=>{:forward => "none"} }, :trusted_signers => { :items => [], :enabled => false, :quantity => 0 }, :viewer_protocol_policy => "allow-all", :min_ttl => 0, :allowed_methods => {:items => ["GET", "HEAD"], :quantity => 2} }, :cache_behaviors => {:items => [], :quantity => 0}, :comment => "#{stage}", :logging => { :enabled => false, :include_cookies => false, :bucket => "", :prefix => "", }, :price_class => "PriceClass_All", :enabled => true, :viewer_certificate => {:cloud_front_default_certificate => true}, :restrictions => { :geo_restriction => {:items => [], :restriction_type => "none", :quantity => 0} }, } }) resp = cf.client.list_distributions resp[:items].each do |distribution| pp distribution end
DNSの設定
CloudFrontでディストリビューションを作成した後、image.staging.example.comのDNS AレコードをCloudFrontで作成したディストリビューションのエイリアスに設定します。