【Ruby on Rails】引入Sidekiq的步骤(本地、Heroku、AWS EC2、Docker、Capistrano)

准备Redis

为了使用Sidekiq,需要有Redis。

在Mac OS上安装Redis

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将更新所有消息的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

当控制器接收到新的消息时,将会异步执行作业。

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

当实际创建新消息时,一开始没有 sidekiq_executed_time,但是几秒钟后重新加载页面就会显示出值,从而确认任务已经正确执行。

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

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时,应该会出现管理页面。

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

刷新 Sidekiq 的 Redis 数据库

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

部署完成后,创建一个工作 dyno。

heroku ps:scale web=1 worker=1

到这一步,Heroku的配置已经完成。

在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的配置

gem 'capistrano-sidekiq', require: false, group: :development
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__.service。

比如说,如果应用程序的名字是myapp,在生产环境下,将会如下所示:

[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文件

当执行这个命令时,Sidekiq会启动。

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'
广告
将在 10 秒后关闭
bannerAds