【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
##### 省略 #####

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

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

刷新 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'