今作っているRuby on Railsでアプリケーションをキャシングをするのに、調べ物をあれこれと。
アプリケーションはHeroku上で動かすのですが、Herokuのドキュメント上にはアプリケーションが再起動する際にはコンパイル後に保存されたディスク上のデータは消えるので、ディスクキャッシュは使えないそうです。なのでHerokuのおすすめとしてはmemcachedを使う事。
ということで、今回はHerokuのプラグインであるMemcacheを使ってキャッシュしてみました。キャッシュの方法は下の3つ。
- ページキャッシュ --> アプリケーションのレイアウトを流用した404や500ページを使用したいのでカスタムでページを作ってページキャッシュ。データも大きくないし、消えてしまっても特に問題無いのでディスクキャッシュで。これは単純に
caches_page :action_name
と書くだけです。
- アクションキャッシュ --> sitemap.xmlをデータベースからデータを引っ張ってきて作成しているので、これをアクションキャッシュで保存。データベースが大きくなる予定なので、botが来る度にxmlを生成しているとパフォーアンスの低下に繋がる可能性が高いです。検索botたちが訪問する頻度はそんなに高くないだろうと思うので、3日で賞味期限が切れる様に設定。多分これで良いと思います…。これも同じくコントローラの最初で
caches_action :action_name, expires_in: 3.days
と記述するだけ。
- 外部API --> ショッピングモールが提供するAPIから商品の情報を引っ張ってきているのですが、このレスポンスがかなり時間がかかっている様です(20個ぐらいの商品情報を引っ張って来るのに2秒近く)。これは取りあえずAPIのデータのみをmemcachedに保存。まずは賞味期限8時間ぐらいで動かしてみます。コントローラ上でmemcacheを使用して幾つかのviewでもキャッシュしたデータを利用できる様にします。製品ごとに販売できる商品を製品のキャッシュデータをデータベースの中のidとupdated_atのタイムスタンプ、それに'buyable'の文字列を付与したインデックスで管理します。
@buyables = Rails.cache.fetch([@product, 'buyables'], expires_in: 8.hours) { @product.buyables }
Showing posts with label cache. Show all posts
Showing posts with label cache. Show all posts
Wednesday, 28 November 2012
Thursday, 24 May 2012
SinatraとHerokuでフレキシブルな静的ファイルサーバ構築
SinatraとHerokuでフレキシブルな静的ファイルサーバ構築をしてみました。実際役に立つかどうか?というのは、用途によります。
SinatraもRailsもgemなどを使ってインストールさせ、サーバを起動すれば /public以下のフォルダをかってに拾ってくれるので、単純なhtmlのサイトであればお手軽に無料でサイトが作成できます。(無料でサイトを作成するという意味であればWordpressやFacebook, Google Pageなどいくらでも便利なつーるはあり、そちらの方が断然便利だと思います。)
Sinatraならではのフレキシブルな点としてはアプリケーションに
get "/folder_name/*"
protect!
File.read("/public/index.html")
end
などとすれば特定のフォルダを簡単にBasic認証で保護できます。
また、Amazon S3の上にファイルを置いて、下のようにすれば特定の(この場合は東北アジアのサーバに置いた)バスケットに見せたいファイルをアップロードすれば普通の静的ファイルサーバの様に見せてくれます。jpgでもhtmlでもpdfでも問題無いはずです。
require 'rubygems'
require 'sinatra'
require 'aws/s3'
include AWS::S3
helpers do
def connect_aws_s3
DEFAULT_HOST.replace "s3-ap-northeast-1.amazonaws.com"
connection = Base.establish_connection!(
:access_key_id => 'YOUR-KEY-ID',
:secret_access_key => 'YOUR-SECRET-ACCESS-KEY'
)
@bucket = Bucket.find('sinatra-aws-s3-test')
end
def protect!(user_name, passwd)
unless authorized?(user_name, passwd)
response['WWW-Authenticate'] = %(Basic realm="Restricted Area")
throw(:halt, [401, "Not authorized\n"])
end
end
def authorized?(user_name, passwd)
@auth ||= Rack::Auth::Basic::Request.new(request.env)
username = user_name
password = passwd
@auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == [username, password]
end
end
get %r{.+} do
protect!("username", "password") if request.path.match(/^\/folder_name/)
connect_aws_s3
file_path = request.path
file_path += "index.html" if file_path.match(/\/$/)
file = @bucket[file_path.gsub(/^\//,"")] rescue throw(:halt, [404, "Page not found\n"])
content_type file.content_type
file.value
end
get %r{.+} do で全てのgetメソッドリクエストに対してアプリケーションが対応する様にしています。
ここで、確かに見せるだけは問題無いのですが、少し大きな動画などのファイルを見せると、S3 Bucketの読み込みに時間がかかるらしくレスポンスがかなり遅くなります。S3のBucketをアメリカのサーバに移しても同じでした。
なのでキャッシングを有効にするためにRack Middlewareを使います。http://rtomayko.github.com/rack-cache/
私の場合は 'rack-cache'と'dalli'のgem をインストールしてconfig.ruに
require 'rack/cache'
require 'dalli'
use Rack::Cache,
:verbose => true,
:metastore => Dalli::Client.new,
:entitystore => 'file:tmp/cache/rack/body'
を加えると読み込みが断然改善されました。でもこうするとHerokuサーバ上に大きなキャッシュのファイルを置くことになるので、直接/publicの下にファイルを置くのと大差ありませんね。実験としては面白いと思いますが、実用的ではないかもしれませんね。
また、Herokuのアプリケーションを動かしているサーバからのレスポンスはサーバがアメリカにあるためこれ以上改善できなさそうです。この点はHerokuが日本のサーバでサーバを提供してくれるのを期待するしかなさそうです。
SinatraもRailsもgemなどを使ってインストールさせ、サーバを起動すれば /public以下のフォルダをかってに拾ってくれるので、単純なhtmlのサイトであればお手軽に無料でサイトが作成できます。(無料でサイトを作成するという意味であればWordpressやFacebook, Google Pageなどいくらでも便利なつーるはあり、そちらの方が断然便利だと思います。)
Sinatraならではのフレキシブルな点としてはアプリケーションに
get "/folder_name/*"
protect!
File.read("/public/index.html")
end
などとすれば特定のフォルダを簡単にBasic認証で保護できます。
また、Amazon S3の上にファイルを置いて、下のようにすれば特定の(この場合は東北アジアのサーバに置いた)バスケットに見せたいファイルをアップロードすれば普通の静的ファイルサーバの様に見せてくれます。jpgでもhtmlでもpdfでも問題無いはずです。
require 'rubygems'
require 'sinatra'
require 'aws/s3'
include AWS::S3
helpers do
def connect_aws_s3
DEFAULT_HOST.replace "s3-ap-northeast-1.amazonaws.com"
connection = Base.establish_connection!(
:access_key_id => 'YOUR-KEY-ID',
:secret_access_key => 'YOUR-SECRET-ACCESS-KEY'
)
@bucket = Bucket.find('sinatra-aws-s3-test')
end
def protect!(user_name, passwd)
unless authorized?(user_name, passwd)
response['WWW-Authenticate'] = %(Basic realm="Restricted Area")
throw(:halt, [401, "Not authorized\n"])
end
end
def authorized?(user_name, passwd)
@auth ||= Rack::Auth::Basic::Request.new(request.env)
username = user_name
password = passwd
@auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == [username, password]
end
end
get %r{.+} do
protect!("username", "password") if request.path.match(/^\/folder_name/)
connect_aws_s3
file_path = request.path
file_path += "index.html" if file_path.match(/\/$/)
file = @bucket[file_path.gsub(/^\//,"")] rescue throw(:halt, [404, "Page not found\n"])
content_type file.content_type
file.value
end
get %r{.+} do で全てのgetメソッドリクエストに対してアプリケーションが対応する様にしています。
ここで、確かに見せるだけは問題無いのですが、少し大きな動画などのファイルを見せると、S3 Bucketの読み込みに時間がかかるらしくレスポンスがかなり遅くなります。S3のBucketをアメリカのサーバに移しても同じでした。
なのでキャッシングを有効にするためにRack Middlewareを使います。http://rtomayko.github.com/rack-cache/
私の場合は 'rack-cache'と'dalli'のgem をインストールしてconfig.ruに
require 'rack/cache'
require 'dalli'
use Rack::Cache,
:verbose => true,
:metastore => Dalli::Client.new,
:entitystore => 'file:tmp/cache/rack/body'
を加えると読み込みが断然改善されました。でもこうするとHerokuサーバ上に大きなキャッシュのファイルを置くことになるので、直接/publicの下にファイルを置くのと大差ありませんね。実験としては面白いと思いますが、実用的ではないかもしれませんね。
また、Herokuのアプリケーションを動かしているサーバからのレスポンスはサーバがアメリカにあるためこれ以上改善できなさそうです。この点はHerokuが日本のサーバでサーバを提供してくれるのを期待するしかなさそうです。
Subscribe to:
Posts (Atom)