平時(shí)的開(kāi)發(fā)中總有一些需要延遲執(zhí)行的程序和一些需要定時(shí)執(zhí)行的程序。
延遲執(zhí)行一般我們使用sidekiq,還是挺好用的,也沒(méi)有什么問(wèn)題,如果有更多需求可以付費(fèi)購(gòu)買(mǎi)PRO版。
定時(shí)任務(wù)之前我們一直使用sidetiq,但是sidetiq在幾年前停止了支持,所以我們要找一個(gè)新的替代gem,它就是sidekiq-cron,看名字就知道是專(zhuān)門(mén)用來(lái)和sidekiq搭配實(shí)現(xiàn)定時(shí)任務(wù)的。
接下來(lái)我們就來(lái)配置異步執(zhí)行(sidekiq)和定時(shí)執(zhí)行(sidekiq-cron)的環(huán)境。
一、安裝Gem包
首先我們先來(lái)安裝 gem,修改Gemfile文件增加兩個(gè)gem
Ruby
gem 'sidekiq'
gem 'sidekiq-cron'
然后執(zhí)行
Bash
bundle install
二、配置 sidekiq
由于sidekiq是基于redis的,所以我們需要給sidekiq配置要使用的redis。
*如果你使用的redis和你的應(yīng)用在同一臺(tái)機(jī)器,那么你就可以不用配置sidekiq的redis了。
新建一個(gè)文件onfig/intializers/sidekiq.rb ,配置如下代碼:
Ruby
Server
Sidekiq.configure_server do |config|
config.redis = { url: "redis://172.16.0.40:6379/15"} # 這里的redis根據(jù)自己需要修改
# 這里是配置 sidekiq-cron 的定時(shí)任務(wù)從 config/sidekiq_cron.yml 文件讀取
schedule_file = 'config/sidekiq_cron.yml'
if File.exist?(schedule_file)
Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file)
end
end
Client
Sidekiq.configure_client do |config|
config.redis = { url: "redis://172.16.0.40:6379/15" } # 這里的redis根據(jù)自己需要修改
end
接下來(lái)是運(yùn)行時(shí)的參數(shù)配置文件
config/sidekiq.yml
Ruby
:concurrency: 5 #并發(fā)線程數(shù)
:pidfile: tmp/pids/sidekiq.pid #進(jìn)程id
:logfile: log/sidekiq.log # 輸出日志文件
staging:
:concurrency: 10
production:
:concurrency: 20
:queues:
- [critical, 2] # 使用數(shù)組的形式寫(xiě), 第一個(gè)參數(shù)為打開(kāi)的 queue 的名稱(chēng), 第二個(gè)為優(yōu)先級(jí)
- default # 寫(xiě)在隊(duì)列參數(shù)中的, 表示讓 sidekiq 處理這個(gè) queue
- low
config/sidekiq_cron.yml
Ruby
my_first_work:
cron: "*/1 * * * *" # 每分鐘執(zhí)行一次,這里的配置方式和系統(tǒng)的crontab配置一樣
class: "TimeKeyClubWorker"
queue: critcal # 指定要進(jìn)入的隊(duì)列,這會(huì)覆蓋sidekiq_options中指定的queue
三、創(chuàng)建 Worker 類(lèi)
創(chuàng)建worker
Ruby
rails g sikiq:worker TimeKeyClub
會(huì)生成文件 /app/workers/time_key_club_worker.rb
修改代碼為如下
Ruby
class TimeKeyClubWorker
include Sidekiq::Worker
sidekiq_options queue: 'critical' #進(jìn)入指定隊(duì)列
def perform(*args)
# Do something
Rails.logger.info('time key club worker running !' + Time.now.strftime('%Y-%m-%d %H:%M:%S'))
end
end
四、啟動(dòng) sidekiq
Bash
bundle exec sidekiq -e production -q default -d # 監(jiān)控default隊(duì)列
bundle exec sidekiq -e production -q critical -d # 監(jiān)控critical隊(duì)列
bundle exec sidekiq -e production -C config/sidekiq.yml -d # 只監(jiān)控并執(zhí)行sidekiq.yml中queues中的隊(duì)列
啟動(dòng)sidekiq的代碼如上,可以看到我們可以只監(jiān)控并運(yùn)行其中的一個(gè)隊(duì)列,這樣我們就可以把不同的隊(duì)列跑在不同的服務(wù)器上,降低某一臺(tái)服務(wù)器的壓力。
啟動(dòng)成功之后我們就可以在日志中看到我們的worker輸出的內(nèi)容了 。
五、注意事項(xiàng)
sidekiq-cron 定時(shí)任務(wù)的運(yùn)行時(shí)間并不是很精確,如上我們的定時(shí)任務(wù),并不是很精確的每60秒執(zhí)行一次。
sidekiq-cron 如果修改了名字需要運(yùn)行代碼刪除原來(lái)的定時(shí)任務(wù),否則會(huì)執(zhí)行多個(gè)定時(shí)任務(wù)
例如:原來(lái)的配置如本文上面的sidekiq_cron.yml
現(xiàn)在把其中的 my_first_work 修改為 my_work ,再次啟動(dòng)sidekiq,我們的worker每分鐘會(huì)執(zhí)行兩次
刪除方法:
Ruby
Sidekiq::Cron::Job.destroy "my_first_work"