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)

Copy
1
brew install redis
redis起動
Copy
1
brew services start redis
docker-composeを使う場合
Copy docker-compose.yml
1
2
3
4
5
6
  redis:
    image: redis:latest
    volumes:
      - redis:/data
    ports:
      - '6379:6379'

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

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

sidekiqを起動する

Copy
1
sidekiq -q default -q mailers
もしくは

Copy config/sidekiq.yml
1
2
3
4
5
6
7
8
9
:concurrency: 25
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log
:queues:
  - default
  - mailers
  - active_storage_analysis
  - active_storage_purge
:daemon: true
Copy
1
sidekiq -C config/sidekiq.yml
サンプル

アプリケーションには Message というモデルがあり、そのモデルが content と sidekiq_executed_time カラムを持ちます。

例えば、SampleJobを作るとします。

Copy
1
rails g job SampleJob
生成したJobは全ての Message の sidekiq_executed_time を現時点に更新します。

Copy app/jobs/sample_job.rb
1
2
3
4
5
6
7
8
9
10
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を非同期実行します。

Copy app/controllers/messages_controller.rb
1
2
3
4
5
6
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ジョブの管理画面

Copy config/routes.rb
1
2
3
4
5
6
7
8
9
10
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

Copy Railsコンソールで
1
Sidekiq.redis { |r| puts r.flushall }

Herokuで使う

Heroku redisの追加

Copy
1
heroku addons:create heroku-redis:hobby-dev
Heroku Redis との接続設定
Copy config/initializes/sidekiq.rb
1
2
3
4
5
6
7
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 の作成

Copy Procfile
1
2
web: bin/rails server -p $PORT -e $RAILS_ENV
worker: bundle exec sidekiq -c 3 -q default -q mailers

デプロイの後、worker dyno を作る

Copy
1
heroku ps:scale web=1 worker=1
AWS EC2で使う

AWS ElastiCache との接続設定

Copy config/initializes/sidekiq.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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の設定

Copy Gemfile
1
gem 'capistrano-sidekiq', require: false, group: :development
Copy Capfile
1
require 'capistrano/sidekiq'
Copy config/deploy.rb
1
2
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をサーバーにインストールする

Copy
1
cap production sidekiq:install
サーバーにアクセスして、sidekiq-production.serviceを修正する

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

上の「/home/deploy/.rbenv/shims/bundle」がwhich bundle で確認できたものです。

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

Copy
1
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を再起動する
Copy
1
cap production sidekiq:restart
Updated by Yuto at 2022-10-09 06:00
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.