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 中设置后台任务的后端为 sidekiq config.active_job.queue_adapter = :sidekiq,另外,不建议再设置这个配置了 config.active_job.queue_name_prefix,我把它注释了,如果你设置了,那么在下文提到的 sidekiq_schedule.ymlsidekiq.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 定时任务配置文件设置,下面给出一个参考,在实际项目中对应修改即可
    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 相关的知识。

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

上面两个命令要在项目的根目录下执行。

推荐阅读:

3 条评论
您想说点什么吗?
黄文威 评论于 2017-01-04 19:31

这又是一条评论

黄文威 评论于 2017-01-04 19:24

截图。

hww 评论于 2017-01-02 01:52

不错。