Rails后台作业运行两次

时间:2017-12-05 23:30:43

标签: ruby-on-rails scheduled-tasks ruby-on-rails-5 rails-activejob rufus-scheduler

我正在使用Rufus Scheduler来触发需要每1小时运行一次的后台作业。

scheduler = Rufus::Scheduler.singleton

scheduler.every '1h' do
 JobName.perform_now
end

我在AWS中进行了Infra设置,并且在生产中,我有2个实例在ECS中运行APP。

调度程序会安排作业两次。

实例A在00:00:05:01安排工作,实例B安排在00:00:05:05

工作没有失败。我正在使用ActiveJob。我正在研究其他解决方案,比如延迟Job,但是当有多个实例时,它会遇到同样的问题。

你们可以提供另一种方法来解决这个问题吗?或者相同的解决方法?

3 个答案:

答案 0 :(得分:1)

https://github.com/jmettraux/rufus-scheduler#lockfile--mylockfiletxt

“这在持有调度程序的Ruby进程多次启动的环境中很有用。”

试试这个:

scheduler = Rufus::Scheduler.singleton(:lockfile => ".rufus-scheduler.lock")

scheduler.every '1h' do
 JobName.perform_now
end

答案 1 :(得分:1)

您需要distributed lock,因为ECS实例不共享文件,最常见的是Zookeeper,Consul和Redis。

在Zookeeper的示例下面,from the docs

class ZookeptScheduler < Rufus::Scheduler

  def initialize(zookeeper, opts={})
    @zk = zookeeper
    super(opts)
  end

  def lock
    @zk_locker = @zk.exclusive_locker('scheduler')
    @zk_locker.lock # returns true if the lock was acquired, false else
  end

  def unlock
    @zk_locker.unlock
  end

  def confirm_lock
    return false if down?
    @zk_locker.assert!
  rescue ZK::Exceptions::LockAssertionFailedError => e
    # we've lost the lock, shutdown (and return false to at least prevent
    # this job from triggering
    shutdown
    false
  end
end

你可能use EFS to share a lockfile,但这不是正确的方法。

答案 2 :(得分:0)

仅启动实例A上的调度程序。