【问题标题】:Rails Background Jobs running twiceRails 后台作业运行两次
【发布时间】:2018-05-19 17:59:47
【问题描述】:

我正在使用 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。我正在研究其他解决方案,例如延迟作业,但是当有多个实例时也会出现同样的问题。

你们能否提供一种替代方法来解决此问题?或者相同的解决方法?

【问题讨论】:

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


    【解决方案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
    

    【讨论】:

    • 我正在使用 AWS 两个类似的实例,所以锁不会有任何好处
    【解决方案2】:

    您需要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,但这不是正确的方法。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 我有一个 docker,我正在将该 docker 部署到 ECS 容器内的多个实例中
      猜你喜欢
      • 1970-01-01
      • 2011-09-10
      • 1970-01-01
      • 1970-01-01
      • 2011-06-17
      • 2014-04-12
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      相关资源
      最近更新 更多