Sidekiq 和 ActiveJob 实现定时循环任务
使用 sidekiq 实现定时循环任务,同时 Linux 系统的 Cron 能做同样的事,但这篇文章讨论使用 sidekiq 结合 ActiveJob 在 Rails 应用中如何实现定时任务。
在早期的 Sidekiq 版本中,也许 sidetip 是实现定时循环任务不错的选择,但是在 Sidekiq4 中移除了 Celluloid, 而 sidetip 必须依赖 Celluloid remove in sidekiq 同时我们还有另外的选择,其中 Sidekiq-cron 也是不错的选择,在 GitHub 上的项目描述是:
Scheduler / Cron for Sidekiq jobs
Sidekiq-crom 简介
这个 Gem 是 Sidekiq 实现定时任务的一个插件,Sidekiq-Cron 的命名让人一开始觉得它实现原理是基于 Linux 的 Cron ,其实不然。下面列出几点需要注意事项。
- 优点
- 简单易用
- 它有一个 Web 页面,能够直接嵌入 sidekiq-web 管理页面中
- 使用 YAML 配置定时任务
- 可与 ActiveJob 结合使用,当然也可单独使用 Sidekiq Worker
- 缺点
- 不兼容 forking processes 的类 Unicorn web 容器
Sidekiq-cron 使用
- 添加到 Gemfile 中
gem "sidekiq-cron", "~> 0.4.0"
然后bundle install
- ActiveJob adapter 设置由于我们是结合 Rails 中的 ActiveJob gem 使用,所有我们要在
config/application.rb
中设置后台任务的后端为 sidekiqconfig.active_job.queue_adapter = :sidekiq
,另外,不建议再设置这个配置了config.active_job.queue_name_prefix
,我把它注释了,如果你设置了,那么在下文提到的sidekiq_schedule.yml
和sidekiq.yml
配置文件中中需要注意 queue 的设置。 sidekiq 设置初始化文件设置,主要是 redis 和 Sidekiq-Cron yaml 配置文件的设置,根据需要可做适当修改。
# config/initializers/sidekiq.rb Sidekiq.configure_client do |config| config.redis = { url: 'redis://127.0.0.1:6379/0/cache', namespace: 'wallet_server' } end Sidekiq.configure_server do |config| config.redis = { url: 'redis://127.0.0.1:6379/0/cache', namespace: 'wallet_server' } schedule_file = "config/sidekiq_schedule.yml" if File.exists?(schedule_file) && Sidekiq.server? Sidekiq::Cron::Job.load_from_hash! YAML.load_file(schedule_file) end end
然后就是 sidekiq 配置文件设置
# config/sidekiq.yml :pidfile: ./tmp/pids/sidekiq.pid :logfile: ./log/sidekiq.log :concurrency: 10 :queues: - get_rake - minconf - send_mail
sidekiq 配置文件需要注意的一个地方就是 concurrency 的设置,推荐阅读 Sidekiq concurrency 设置和一些注意事项 了解一下具体原因。
- Sidekiq-cron 定时任务配置文件设置,下面给出一个参考,在实际项目中对应修改即可
以上就是一些设置,接下来讨论 ActiveJob 相关的知识。get_rake_job: description: "get rake every 1 min" cron: "*/1 * * * *" class: "GetRakeJob" queue: get_rake active_job: true minconf_job: description: "get minconf every 5 min" cron: "*/5 * * * *" class: "MinconfJob" queue: minconf active_job: true
ActiveJob 使用
在 Rails 中使用 rails g job get_rake
命令可生成一个 app/jobs/get_rake_job.rb 文件。
class GetRakeJob < ApplicationJob
queue_as :get_rake
def perform(*args)
BlockChainWallet::AppLogger.info "====start assets rake job============"
Rails.cache.write("btc_rake", Account.asset_rake("btccny", SettingConfig.yunbi_api).to_f.cny_to_usd)
Rails.cache.write("eth_rake", Account.asset_rake("ethcny", SettingConfig.yunbi_api).to_f.cny_to_usd)
Rails.cache.write("sdc_rake", Account.asset_rake("sdccny", SettingConfig.brockex_api).to_f.cny_to_usd)
Rails.cache.write("peb_rake", Account.asset_rake("pebkrw", SettingConfig.loicoin_api).to_f.krw_to_usd)
Rails.cache.write("cfc_rake", Account.asset_rake("cfckrw", SettingConfig.loicoin_api).to_f.krw_to_usd)
BlockChainWallet::AppLogger.info "====get assets rake job done============"
# Do something later
end
end
Active Job Basics 这是 ActiveJob 的文档,更加高级的使用技巧可查阅文档学习。其中回调的特性比较有用,事物进行前,进行中,结束后总得做点什么。 可用的回调如下:
before_enqueue
around_enqueue
after_enqueue
befer_perform
around_perform
after_perfom
官方给出的一个回调使用例子
class GuestsCleanupJob < ApplicationJob
queue_as :default
before_enqueue do |job|
# Do something with the job instance
end
around_perform do |job, block|
# Do something before perform
block.call
# Do something after perform
end
def perform
# Do something later
end
end
定时任务启动及停止
- 启动
bundle exec sidekiq -C config/sidekiq.yml -e production -d
- 停止
sidekiqctl stop tmp/pids/sidekiq.pid 0 -e production
上面两个命令要在项目的根目录下执行。
推荐阅读: