概要
ActionMailerでdeliver_later
するため、以下を参考にしながらSidekiq
(とRedis
)を導入したのでその備忘録です。
gemを追加
gem 'sidekiq' gem 'redis'
$ bundle install
します。
Sidekiqを有効化
# config/application.rb config.active_job.queue_adapter = :sidekiq
Web UI to Monitor Jobsを有効化
Sidekiq::Web
をconfig/routes.rb
にマウントします。これにより、SidekiqのダッシュボードをWebブラウザから閲覧できるようになります。
# config/routes.rb require 'sidekiq/web' Myapp::Application.routes.draw do # mount Sidekiq::Web in your Rails app mount Sidekiq::Web => "/sidekiq" end
mount
:これはRailsのルーティングのメソッドで、特定のパスにRackベースのアプリケーションをマウントするために使用されます。RackはRubyでWebサーバーとアプリケーションを接続するためのインターフェースで、RailsもSinatraもRackベースのフレームワークです。Sidekiq::Web
:これはSidekiqが提供するSinatraベースのWebアプリケーションで、Sidekiqのダッシュボードを提供します。このダッシュボードを通じて、現在のジョブの状態、ジョブの履歴、統計情報などを閲覧することができます。
設定ファイルを作成
config/initializers/sidekiq.rb
redis_config = YAML.load_file('config/redis.yml')[Rails.env] redis_config['db'] = redis_config['db']['sidekiq'] Sidekiq.configure_server do |config| config.redis = { url: "redis://#{redis_config['host']}/#{redis_config['db']}" } end Sidekiq.configure_client do |config| config.redis = { url: "redis://#{redis_config['host']}/#{redis_config['db']}" } end
このコードは、Rubyのジョブキュー処理ライブラリであるSidekiqの初期化設定を行うものです。
まず、最初の3行では、config/redis.yml
から現在の環境(Rails.env
)に対応するRedisの設定をロードしています。その中で特にSidekiqが使用するデータベース(db
)を指定します。
redis_config = YAML.load_file('config/redis.yml')[Rails.env] redis_config['db'] = redis_config['db']['sidekiq']
次に、Sidekiqがサーバーモードで起動した時の設定を行います。configure_server
メソッドを用いて、Sidekiqがジョブを処理するために接続するRedisサーバーの設定を行います。ここで指定された設定はサーバーモードでのみ有効です。
Sidekiq.configure_server do |config| config.redis = { url: "redis://#{redis_config['host']}/#{redis_config['db']}" } end
最後に、Sidekiqがクライアントモードで起動した時の設定を行います。configure_client
メソッドを用いて、Sidekiqがジョブをキューにプッシュするために接続するRedisサーバーの設定を行います。ここで指定された設定はクライアントモードでのみ有効です。
Sidekiq.configure_client do |config| config.redis = { url: "redis://#{redis_config['host']}/#{redis_config['db']}" } end
これらの設定により、Sidekiqは指定されたRedisサーバーを用いてジョブのキューイングと処理を行うようになります。
config/redis.yml
default: &default db: sidekiq: 0 development: <<: *default host: redis test: <<: *default host: redis staging: <<: *default host: localhost
このコードは、アプリケーションのRedis設定を行うYAMLファイルです。
まず、default
セクションでは、デフォルトの設定を定義しています。ここでは、異なるデータタイプごとにRedisデータベースを分けています。Sidekiqはデータベース0
を使用します。これにより、それぞれのデータタイプが他のデータに影響を及ぼすことなく、同じRedisインスタンスを利用することができます。
default: &default db: sidekiq: 0
次に、各環境(開発、テスト、ステージング)の設定を定義しています。ここでは<<: *default
を使ってデフォルトの設定を継承し、それぞれの環境でRedisサーバーのホスト名を指定しています。開発環境とテスト環境ではredis
を、ステージング環境ではlocalhost
をホスト名として使用します。
development: <<: *default host: redis test: <<: *default host: redis staging: <<: *default host: localhost
これにより、各環境ごとにRedisの接続設定を独立させることができます。これは、例えば開発環境と本番環境で異なるRedisサーバーを使用したいといったケースで有用です。
config/sidekiq.yml
:verbose: false :pidfile: ./tmp/pids/sidekiq.pid :logfile: ./log/sidekiq.log :concurrency: 10 :queues: - default - test
このコードは、Sidekiqの設定ファイル config/sidekiq.yml
の一部です。SidekiqはRubyのバックグラウンドジョブ処理ライブラリで、非同期にタスクを実行するために使用されます。
:verbose: false
: Sidekiqがログに詳細な情報を出力するかどうかを制御します。ここでは、冗長な(verbose)出力をオフにしています。:pidfile: ./tmp/pids/sidekiq.pid
: SidekiqのプロセスIDを保存するためのファイルのパスを指定します。これはサーバーが起動している間、そのプロセスIDを保持します。:logfile: ./log/sidekiq.log
: Sidekiqのログが出力されるファイルのパスを指定します。:concurrency: 10
: 同時に実行可能なジョブの最大数を指定します。この場合、10個のジョブを同時に処理できます。:queues:
: このセクションでは、Sidekiqがジョブを検索するキューの名前を指定します。Sidekiqは上から順にキューをチェックし、ジョブが存在すればそのジョブを実行します。ここでは 'default' と 'test' という2つのキューが設定されています。
コラム:concurrencyは何を指定するのが妥当か?
Sidekiqの concurrency
設定は、同時に処理されるジョブの数を指定します。適切な値は、アプリケーションの具体的な要件と、ホストシステムのリソース(CPU、メモリ、I/Oなど)に大きく依存します。
一般的なガイドラインとして、以下のような考え方があります:
- CPUの数とスレッドの数: CPUコアの数と同じ、またはそれより少し多い数の並行性が良いとされています。ただし、あまりに多くのスレッドを作成すると、システムのオーバーヘッドが大きくなり、パフォーマンスが低下する可能性があります。
- I/O待ちの時間: I/O待ちが多い(データベースへのクエリ、ネットワークリクエストなど)ジョブの場合、より高い並行性が有効になることがあります。これは、一部のジョブがI/Oによってブロックされている間に、他のジョブがCPUを使用できるからです。
- メモリ: 各スレッドはメモリを消費します。したがって、メモリ不足を引き起こさないためには、使用可能なメモリに基づいて並行性を設定する必要があります。
具体的な値を決めるには、異なる concurrency
の値で実際にテストを行い、パフォーマンスを評価するのが最善の方法です。
Dockerを使用している場合
# == ここから == redis: image: redis:latest ports: - "6379:6379" volumes: - "./tmp/cache/redis:/data" - "./db/redis.conf:/etc/redis.conf" # == ここまで == # 省略 app: &app tty: true stdin_open: true build: . command: bin/dev volumes: - .:/opt/app - app-bundle:/usr/local/bundle ports: - "3000:3000" - "3030:3030" - "3035:3035" depends_on: - db - redis - mail environment: REDIS_URL: redis://redis:6379 # 追加 # == ここから == sidekiq: <<: *app command: bundle exec sidekiq ports: [] depends_on: - db - redis # == ここまで追加 ==