如何在 Heroku 上处理 运行 长的作业?
How do I handle long running jobs on Heroku?
我想使用 Heroku,但事实上他们每 24 小时随机重启一次测功机,这让事情变得有点困难。
我有一系列非常重要的处理支付处理的工作,我希望它们得到数据库的支持,以便它们 100% 可靠。为此,我选择了速度较慢的DJ。
因为我选择了 DJ,这意味着我也不能一次将 5,000,000 个事件推送到数据库(每封电子邮件发送 1 个)。
正因为如此,我有更长的 运行 工作(在几个小时内发送 200,000 条短信)。
对于这些较长的 运行 作业,如果它们在中间被切断,则让它们继续工作会更具挑战性。
heroku 似乎发送了 SIGTERM
,然后期望进程在 30 秒内关闭。这不会发生在我的长期工作中。
现在我不确定如何处理它们...我能想到的唯一方法是在发送文本(例如 sms_sent_at
列)后立即更新数据库,但是只是意味着我正在破坏数据库性能,而不是为每个批次发送一个更新查询。
如果我可以安排重新启动,这会好很多,至少我可以在晚上完成,那时我 99% 可能不会 运行 任何不需要更长时间的工作关机时间少于 30 秒。
或者.. 换句话说,我可以 'listen' for SIGTERM
在一个长的 运行 DJ 中并且至少提前中止循环以便稍后可以恢复吗?
手动重启将重置 24 小时时钟 - heroku ps:restart
在您喜欢的时间应该可以让您获得所需的控制权。
可以在此处找到更多信息:Dynos and the Dyno Manager
这是正确的答案,你听 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
我想使用 Heroku,但事实上他们每 24 小时随机重启一次测功机,这让事情变得有点困难。
我有一系列非常重要的处理支付处理的工作,我希望它们得到数据库的支持,以便它们 100% 可靠。为此,我选择了速度较慢的DJ。
因为我选择了 DJ,这意味着我也不能一次将 5,000,000 个事件推送到数据库(每封电子邮件发送 1 个)。
正因为如此,我有更长的 运行 工作(在几个小时内发送 200,000 条短信)。
对于这些较长的 运行 作业,如果它们在中间被切断,则让它们继续工作会更具挑战性。
heroku 似乎发送了 SIGTERM
,然后期望进程在 30 秒内关闭。这不会发生在我的长期工作中。
现在我不确定如何处理它们...我能想到的唯一方法是在发送文本(例如 sms_sent_at
列)后立即更新数据库,但是只是意味着我正在破坏数据库性能,而不是为每个批次发送一个更新查询。
如果我可以安排重新启动,这会好很多,至少我可以在晚上完成,那时我 99% 可能不会 运行 任何不需要更长时间的工作关机时间少于 30 秒。
或者.. 换句话说,我可以 'listen' for SIGTERM
在一个长的 运行 DJ 中并且至少提前中止循环以便稍后可以恢复吗?
手动重启将重置 24 小时时钟 - heroku ps:restart
在您喜欢的时间应该可以让您获得所需的控制权。
可以在此处找到更多信息:Dynos and the Dyno Manager
这是正确的答案,你听 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