redisを準備する
sidekiqを使う為にredisが必要です。
Macでインストールする場合
brew install redis
redis起動
brew services start redis
docker-composeを使う場合
redis:
image: redis:latest
volumes:
- redis:/data
ports:
- '6379:6379'
アプリケーションにsidekiqを導入する
gem 'sidekiq'
config.active_job.queue_adapter = :sidekiq
sidekiqを起動する
sidekiq -q default -q mailers
もしくは、以下の設定ファイルを作成して、簡単に起動できます。
:concurrency: 25
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log
:queues:
- default
- mailers
- active_storage_analysis
- active_storage_purge
:daemon: true
sidekiq -C config/sidekiq.yml
サンプルアプリケーション
アプリケーションには Message
というモデルがあり、そのモデルが content
と sidekiq_executed_time
カラムを持つとします。
例えば、SampleJob
を作ります。
rails g job Sample
生成したJobは全ての Message
の sidekiq_executed_time
を現時点に更新します。
class SampleJob < ApplicationJob
queue_as :default
def perform(*args)
sleep(1)
Message.find_each do |message|
message.update(sidekiq_executed_time: DateTime.current)
end
end
end
コントローラーでは、新規 Message が作成された時に、Jobを非同期実行します。
def create
@message = Message.new(message_params)
if @message.save
redirect_to messages_path, notice: 'Message was successfully created.'
SampleJob.perform_later
##### 省略 #####
実際に新規 Message
を作成したら、最初は sidekiq_executed_time
がなかったが、数秒後ページをリロードすると値があって、Jobがちゃんと実行されたことが分かります。
sidekiqジョブの管理画面
require 'sidekiq/web'
Rails.application.routes.draw do
mount Sidekiq::Web => '/sidekiq'
# 認証が必要の場合
Sidekiq::Web.use(Rack::Auth::Basic) do |user, password|
[user, password] == [ENV['SIDEKIQ_USERNAME'], ENV['SIDEKIQ_PASSWORD']]
end
##### 省略 #####
そして、localhost:3000/sidekiq
にアクセスすると管理画面が現れるはずです。
Redis DBのデータを全て削除する
Railsコンソールで以下のコマンドを実行すると、Redis DBのデータを全て削除することができます。
Sidekiq.redis { |r| puts r.flushall }
Herokuで使う場合
Heroku redisの追加
heroku addons:create heroku-redis:hobby-dev
Heroku Redis との接続設定
Sidekiq.configure_server do |config|
config.redis = { url: ENV.fetch('REDIS_URL', 'redis://localhost:6379') }
end
Sidekiq.configure_client do |config|
config.redis = { url: ENV.fetch('REDIS_URL', 'redis://localhost:6379')}
end
Procfile の作成
web: bin/rails server -p $PORT -e $RAILS_ENV
worker: bundle exec sidekiq -c 3 -q default -q mailers
デプロイの後、worker dyno を作る
heroku ps:scale web=1 worker=1
AWS EC2で使う場合
AWS ElastiCache との接続設定
Sidekiq.configure_server do |config|
if Rails.env.production?
redis_conn = proc {
Redis.new(host: ENV['AWS_REDIS_ENDPOINT'], port: 6379, db: 2)
}
config.redis = ConnectionPool.new(size: 27, &redis_conn)
else
config.redis = { url: ENV.fetch('REDIS_URL', 'redis://localhost:6379') }
end
end
Sidekiq.configure_client do |config|
if Rails.env.production?
redis_conn = proc {
Redis.new(host: ENV['AWS_REDIS_ENDPOINT'], port: 6379, db: 2)
}
config.redis = ConnectionPool.new(size: 27, &redis_conn)
else
config.redis = { url: ENV.fetch('REDIS_URL', 'redis://localhost:6379') }
end
end
capistrano-sidekiqの設定
group: :development do
gem 'capistrano-sidekiq', require: false
end
require 'capistrano/sidekiq'
set :rbenv_map_bins, fetch(:rbenv_map_bins).to_a.concat(%w(rake gem bundle ruby rails puma pumactl sidekiq sidekiqctl))
set :init_system, :systemd
sidekiqをサーバーにインストールする
cap production sidekiq:install
そして、サーバーにアクセスして、sidekiq-production.service
を修正する必要があります。
ExecStart=/home/deploy/.rbenv/shims/bundle exec sidekiq -e production -C config/sidekiq.yml
上の/home/deploy/.rbenv/shims/bundle
がwhich bundle
で確認できたものです。
修正が終わってから、以下のコマンドを実行する
loginctl enable-linger deploy && systemctl --user daemon-reload && systemctl --user stop sidekiq-production.service && systemctl --user daemon-reload && systemctl --user start sidekiq-production.service && systemctl --user enable sidekiq-production.service
sidekiqを再起動する
cap production sidekiq:restart
capistrano-sidekiqを使いたくない場合
capistrano-sidekiq
の設定が面倒だったら、別のやり方があります。
同サーバーに複数のアプリケーションを運用する場合は、このやり方をお勧めします。
.serviceファイルを作成する
サーバーでこのようなファイルを作成します。
/etc/systemd/system/sidekiq_<application>_<stage>.service
例えば、アプリ名はmyapp
、production
環境であれば、以下のようになります:
[Unit]
Description=sidekiq for myapp (production)
After=syslog.target network.target
[Service]
Type=simple
Environment=RAILS_ENV=production
WorkingDirectory=/deploy/apps/myapp/current
# When using anyenv: "/home/deploy/.anyenv/envs/rbenv/shims/bundle"
ExecStart=/home/deploy/.rbenv/shims/bundle exec sidekiq -e production -C config/sidekiq.yml
ExecReload=/bin/kill -TSTP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
RestartSec=1
Restart=on-failure
SyslogIdentifier=sidekiq
[Install]
WantedBy=default.target
.serviceファイルを有効にする
これを実行します。
sudo systemctl enable sidekiq_myapp_production.service
capistranoのタスクを作成する
capistrano
でデプロイした後で、sidekiqを再起動するためです。
namespace :sidekiq do
desc 'Restart sidekiq before finishing deployment'
task :restart do
on roles(:app) do
execute "sudo systemctl restart sidekiq_#{fetch(:application)}_#{fetch(:stage)}.service"
end
end
end
before 'deploy:finishing', 'sidekiq:restart'