Yuto Blog

Yuto Blog

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

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

redisを準備する

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

redisインストール(Mac OS)

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 SampleJob

生成したJobは全ての Message の sidekiq_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

Flush Sidekiq's Redis DB

Railsコンソールで
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
gem 'capistrano-sidekiq', require: false, group: :development
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/bundle」がwhich bundle で確認できたものです。

修正が終わってから、以下のコマンドを実行する

sudo systemctl daemon-reload && systemctl --user reenable sidekiq-production.service && systemctl --user stop sidekiq-production.service && systemctl --user start sidekiq-production.service && sleep 3 && systemctl --user status sidekiq-production.service

sidekiqを再起動する

cap production sidekiq:restart

>>> サンプルアプリケーション

Updated by Yuto at 2022-01-20 23:55
1
Like this article
Le Minh Thien Toan

Tác giả:Yuto Yasunaga

Xin chào các bạn. Mình là kỹ sư IT đang làm việc ở Nhật Bản. Mình tạo blog này để chia sẻ về cuộc sống và những kinh nghiệm trong quá trình học tập và làm việc.
Hy vọng bài viết này sẽ có ích cho bạn.