【问题标题】:How do I handle long running jobs on Heroku?如何在 Heroku 上处理长时间运行的作业?
【发布时间】:2017-03-12 12:25:00
【问题描述】:

我想使用 Heroku,但事实上他们每 24 小时随机重启一次 dynos,这让事情变得有点困难。

我有一系列非常重要的支付处理工作,我希望它们有数据库支持,因此它们是 100% 可靠的。为此,我选择了速度较慢的DJ。

因为我选择了 DJ,这意味着我也不能一次将 5,000,000 个事件推送到数据库(每个电子邮件发送 1 个)。

因此,我的作业运行时间更长(在几个小时内发送 200,000 条短信)。

对于这些运行时间较长的作业,如果它们在中间被切断,那么让它们工作起来更具挑战性。

heroku 似乎发送了SIGTERM,然后期望进程在 30 秒内关闭。这不会发生在我的长期工作中。

现在我不确定如何处理它们......我能想到的唯一方法是在发送文本后立即更新数据库(例如,sms_sent_at 列),但这只是意味着我' m 破坏数据库性能,而不是为每个批次发送单个更新查询。

如果我可以安排重启时间会好很多,至少我可以在晚上进行,那时我 99% 的可能性不会运行任何不超过 30 秒即可关闭的作业.

或者..另一种方式,我可以在长时间运行的 DJ 中“收听”SIGTERM 并至少提前中止循环以便稍后恢复吗?

【问题讨论】:

    标签: ruby-on-rails ruby heroku delayed-job ruby-on-rails-5


    【解决方案1】:

    这是正确的答案,你听 SIGTERM(我在这里使用DJ)然后优雅地救援。重要的是作业是幂等的。

    Long running delayed_job jobs stay locked after a restart on Heroku

    class WithdrawPaymentsJob
    
      def perform
        begin
          term_now = false
          old_term_handler = trap('TERM') { term_now = true; old_term_handler.call }
    
          loop do
    
            puts 'doing long running job'
            sleep 1
    
            if term_now
              raise 'Gracefully terminating job early...'
            end
          end
    
        ensure
          trap('TERM', old_term_handler)
        end
      end
    
    end
    

    这是使用Que 解决问题的方法:

        if Que.worker_count.zero?
          raise 'Gracefully terminating job early...'
        end
    

    【讨论】:

      【解决方案2】:

      手动重启将重置 24 小时制 - heroku ps:restart 在您的首选时间应该会给您所需的控制权。

      更多信息可以在这里找到:Dynos and the Dyno Manager

      【讨论】:

        猜你喜欢
        • 2019-06-06
        • 1970-01-01
        • 2020-04-26
        • 2020-07-08
        • 1970-01-01
        • 2016-03-23
        • 1970-01-01
        • 2012-06-23
        • 1970-01-01
        相关资源
        最近更新 更多