Ruby on rails Rails后台作业运行两次

Ruby on rails Rails后台作业运行两次,ruby-on-rails,scheduled-tasks,ruby-on-rails-5,rails-activejob,rufus-scheduler,Ruby On Rails,Scheduled Tasks,Ruby On Rails 5,Rails Activejob,Rufus Scheduler,我使用Rufus调度程序触发需要每1小时运行一次的后台作业 scheduler = Rufus::Scheduler.singleton scheduler.every '1h' do JobName.perform_now end 我在AWS中安装了Infra,对于生产,我有两个实例在ECS中运行该应用程序 发生的情况是调度程序将作业调度两次 实例A将作业安排在00:00:05:01,实例B将作业安排在00:00:05:05 工作并没有失败。我正在使用ActiveJob。我正在研究其他解

我使用Rufus调度程序触发需要每1小时运行一次的后台作业

scheduler = Rufus::Scheduler.singleton

scheduler.every '1h' do
 JobName.perform_now
end
我在AWS中安装了Infra,对于生产,我有两个实例在ECS中运行该应用程序

发生的情况是调度程序将作业调度两次

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

工作并没有失败。我正在使用ActiveJob。我正在研究其他解决方案,如延迟作业,但当存在多个实例时,也存在同样的问题

你们能提供另一种方法来解决这个问题吗?还是针对同一问题的解决方法?

“这在包含调度程序的Ruby进程多次启动的环境中非常有用。”

试试这个:

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

scheduler.every '1h' do
 JobName.perform_now
end
ECS实例不共享文件,最常见的是Zookeeper、Concur和Redis,所以您需要一个共享文件

下面是Zookeeper的示例:

类ZookeptSchedulere #我们失去了锁,关机(并返回false)以至少防止 #这项工作不会触发 关闭 假的 结束 结束
您可以,但这不是正确的方法。

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

我使用AWS两个类似的实例,因此锁不会起任何作用。我有一个docker,我正在将该docker部署到ECS容器中的多个实例中
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