Heroku Redis で Railsのセッションストアとバックグラウンドジョブ
こんにちは、本間です。
本日、Heroku が Heroku Redis として新アドオンを発表しましたので、早速利用してみることにしました。Herokuの新しい料金体系にて、バックグラウンドジョブが1プロセス無料になったことにより、RailsではActiveJobなどを利用してこのRedisをバックグラウンドジョブのキューとして気軽に利用できるようになりました。今回は簡単にその導入手順をまとめてみたいと思います。
セッションストアとしてのRedis
ご存知の通り、Railsのセッションはデフォルトでは Cookie に保存しており、こちらが毎度議論になるセキュリティの話になってきます。こちらの話は置いておいて、結局のところ、Redisのようなセッションストレージに保存しておけばこれら問題は解決できます。ですので積極的に利用していきましょう。
Railsのセッションストアの指定に移ります。まずはGemfileに以下を追加します。
gem 'redis'
gem 'redis-rails'
config/initializers/session_store.rb
にはデフォルトでCookieの保存先を指定していますが、それを以下のようにRedisに保存させます。
Rails.application.config.session_store :redis_store, servers: ENV['REDIS_URL'], expire_in: 90.minutes
これだけでセッションをRedisに保存できるようになりました。
バックグラウンドジョブとしてのRedis
続いてはバックグラウンドジョブを実現してみます。Rails4.2 から導入されたActiveJobにアダプタとしてResque を利用します。
まずは Gemfileにgem 'resque' gem 'resque-scheduler'
を追加します。
ResqueはRedisを利用しますので以下を追記。
Resque.redis = Redis.new(:url => ENV['REDIS_URL'])
Resque.after_fork = Proc.new { ActiveRecord::Base.establish_connection }
config/initializers/resque.rb
require 'resque/tasks'
require 'resque/scheduler/tasks'
namespace :resque do
task :setup do
require 'resque'
require 'resque-scheduler'
ENV['QUEUE'] ||= '*'
Resque.before_fork = Proc.new { ActiveRecord::Base.establish_connection }
end
end
lib/tasks/resque.rake
あとはActiveJobの記法に従ってバックグラウンドジョブを記述していくのみです。
ActionMailerも deliver_later
として非同期処理にしてみましょう。
TERM_CHILD=1 QUEUE=default rake environment resque:work
bundle exec rails server
の2つを起動して、お互いが非同期処理のやりとりをできているかを確認します。
Heroku に適用
まずはじめに、新しい料金体系のFreeプランに変更し、Workerプロセスをオンにしましょう。
早速、新アドオンを入れてみます。
heroku addons:create heroku-redis:test
まだtestですがそれでも今後間違いなくこちらはアップグレードされていきますし、何せHeroku公式のアドオンですから信頼できます。これでHerokuの環境変数 REDIS_URL が登録されます。
次にHeroku では Procfile と呼ばれるプロセス起動のための命令ファイルを記述します。web, worker それぞれ起動するタスクを記述します。webは今回はthinを利用しています。
web: bundle exec rails server thin -p $PORT -e $RACK_ENV
worker: TERM_CHILD=1 rake environment resque:work
以上でHerokuでWorker プロセスとの連携は完了です。重い処理は積極的にワーカープロセスで実行していくようにしましょう!