やったこと
Railsアプリに、RedisコンテナとSidekiqコンテナを載せた。
なんのために?
- 非同期処理:時間のかかるタスクやある時間になったら実行したいタスクを「後で処理するリスト」に入れておき、他のタスクを実行しながら「後で処理するリスト」のタスクも並列で行っていく
- 「後で処理するリスト」には Redis のキューがよく使われる。これから処理していく予定のジョブのデータをRedisに永続化することで、Railsプロセスが落ちたとしてもエンキューされたジョブのデータは失われない
- Railsサーバと Redis と Sidekiq の関係:Railsサーバの処理の中で「後で処理するリスト」に任せたいジョブがあれば、 Redis で永続化しているキューにジョブを追加(エンキュー)し、 Sidekiq がジョブを取り出して(デキュー)実行していく
- ↑これらのキュー操作をさまざまな方法で実行するためにインターフェースなどを定めているフレームワークがActive Job
手順
- ローカルで動かす
- SidekiqとRedisの詳細設定
- 動作確認
ローカルで動かす
Redisをインストールし、Redisサーバーを起動
(起動させた状態で、Sidekiqを実行していく)
$ brew install redis
$ redis-server
Sidekiqのインストールと実行
# Gemfileにsidekiqを追加後
$ bundle
$ bundle exec sidekiq
Redis, Sidekiqの起動を確認できたら詳細設定をしていく。
SidekiqとRedisの詳細設定
RailsとSidekiqの連携
development環境では、sidekiqを、test環境ではtestをキューアダプターに設定し、環境によって非同期処理の挙動を変える。
# config/environments/development.rb
config.active_job.queue_adapter = :sidekiq
# config/environments/test.rb
config.active_job.queue_adapter = :test
Redisの場所を定義
sidekiq server: キューからjobを取ってきて実行する役割
sidekiq client: キューにjobを追加する役割
(参考)
# config/initializers/sidekiq.rb
Sidekiq.configure_server do |config|
config.redis = { url: ENV['REDIS_URL'] }
end
Sidekiq.configure_client do |config|
config.redis = { url: ENV['REDIS_URL'] }
end
Sidekiqのルーティング追加
Sidekiqのダッシュボードにアクセスできるように設定。
(mount
: 本体アプリケーションから独立したアプリケーションのルーティングを定義)
# config/routes.rb
if Rails.env.development?
require 'sidekiq/web'
mount Sidekiq::Web, at: '/sidekiq'
end
Sidekiqのジョブのオプション設定
- ジョブの同時実行数を5にしてクラッシュ回避(デフォルトは10)
- ジョブは全て
default
キューに入るようにする
# config/sidekiq.yml
:concurrency: 5
:queues:
- default
コンテナ定義
sidekiqコンテナとredisコンテナを定義する。
# docker-compose.yml 追加分
web:
environment:
REDIS_URL: redis://redis:6379
sidekiq:
build: . # webコンテナと同じイメージを使用
environment:
REDIS_URL: redis://redis:6379
volumes:
- .:/karoyaka:cached
- bundle:/usr/local/bundle
depends_on:
- db
- redis
command: bundle exec sidekiq
redis:
image: redis:latest
ports:
- 6379:6379
volumes:
- redis:/data
volumes:
redis:
動作確認
コンテナ起動させ、サンプルジョブを作成し、コンテナ再起動し、サンプルジョブを認識させる。
railsコンソールでジョブを登録して、ダッシュボード(http://localhost:***/sidekiq
)確認。
$ docker-compose up
$ docker-compose run web rails g sidekiq:job sample
$ docker-compose up
$ docker-compose run web rails c
irb(main)> SampleJob.perform_async
sidekiqコンテナ、redisコンテナが正常に動作していることを確認できた