12
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Ruby on Rails】sidekiqの導入手順(ローカル、Heroku、AWS EC2、Docker、Capistrano)

Last updated at Posted at 2020-08-14

redisを準備する

sidekiqを使う為にredisが必要です。

Macでインストールする場合

brew install redis

redis起動

brew services start redis

docker-composeを使う場合

docker-compose.yml
  redis:
    image: redis:latest
    volumes:
      - redis:/data
    ports:
      - '6379:6379'

アプリケーションにsidekiqを導入する

Gemfile
gem 'sidekiq'
config/application.rb
config.active_job.queue_adapter = :sidekiq

sidekiqを起動する

sidekiq -q default -q mailers

もしくは、以下の設定ファイルを作成して、簡単に起動できます。

config/sidekiq.yml
: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は全ての Messagesidekiq_executed_time を現時点に更新します。

app/jobs/sample_job.rb
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を非同期実行します。

app/controllers/messages_controller.rb
def create
  @message = Message.new(message_params)
  if @message.save
    redirect_to messages_path, notice: 'Message was successfully created.'
    SampleJob.perform_later
##### 省略 #####

スクリーンショット 0002-08-15 0.14.02.png

実際に新規 Message を作成したら、最初は sidekiq_executed_time がなかったが、数秒後ページをリロードすると値があって、Jobがちゃんと実行されたことが分かります。

スクリーンショット 0002-08-15 0.14.15.png

sidekiqジョブの管理画面

config/routes.rb
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にアクセスすると管理画面が現れるはずです。

スクリーンショット 0002-08-15 0.20.15.png

Redis DBのデータを全て削除する

Railsコンソールで以下のコマンドを実行すると、Redis DBのデータを全て削除することができます。

Sidekiq.redis { |r| puts r.flushall }

Herokuで使う場合

Heroku redisの追加

heroku addons:create heroku-redis:hobby-dev

Heroku Redis との接続設定

config/initializes/sidekiq.rb
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 との接続設定

config/initializes/sidekiq.rb
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の設定

Gemfile
group: :development do
  gem 'capistrano-sidekiq', require: false
end
Capfile
require 'capistrano/sidekiq'
config/deploy.rb
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を修正する必要があります。

/home/USER/.config/systemd/user/sidekiq-production.service
ExecStart=/home/deploy/.rbenv/shims/bundle exec sidekiq -e production -C config/sidekiq.yml

上の/home/deploy/.rbenv/shims/bundlewhich 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

例えば、アプリ名はmyappproduction環境であれば、以下のようになります:

/etc/systemd/system/sidekiq_myapp_production.service
[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を再起動するためです。

lib/capistrano/tasks/sidekiq.rake
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'
12
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?