Cuộc sống Nhật Bản
Yuto Blog

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

Nội dung chính
【Ruby on Rails】sidekiqの導入手順(ローカル、Heroku、AWS EC2、Docker、Capistrano)

redisを準備する

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

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

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

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

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

Copy ruby
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 zsh
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
2
3
group: :development do
  gem 'capistrano-sidekiq', require: false
end
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 zsh
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/bundlewhich bundle で確認できたものです。

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

Copy zsh
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 zsh
1
cap production sidekiq:restart

capistrano-sidekiqを使いたくない場合

capistrano-sidekiqの設定が面倒だったら、別のやり方があります。
同サーバーに複数のアプリケーションを運用する場合は、このやり方をお勧めします。

.serviceファイルを作成する

サーバーでこのようなファイルを作成します。
/etc/systemd/system/sidekiq_<application>_<stage>.service

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

Copy /etc/systemd/system/sidekiq_myapp_production.service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[Unit]
Description=sidekiq for myapp (production)
After=syslog.target network.target

[Service]
Type=simple
Environment=RAILS_ENV=production
WorkingDirectory=/deploy/apps/myapp/current
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ファイルを有効にする

これを実行します。

Copy zsh
1
sudo systemctl enable sidekiq_myapp_production.service

capistranoのタスクを作成する

capistranoでデプロイした後で、sidekiqを再起動するためです。

Copy lib/capistrano/tasks/sidekiq.rake
1
2
3
4
5
6
7
8
9
10
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'
Updated at 2024-01-08
Nếu bài viết có ích thì các bạn hãy chia sẻ nhé
Rate this article: 5/5 (17 ratings)
You didn't rate yet
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.