【问题标题】:Rails, ActiveJobs and AWS SQS: what happen to my jobs when a worker instance is killed?Rails、ActiveJobs 和 AWS SQS:当一个工作实例被杀死时,我的工作会发生什么?
【发布时间】:2026-01-03 12:45:02
【问题描述】:

我们在 AWS Beanstalk 中使用 Rails 5.0.2 和 ActiveJobs,并将 SQS 作为后端,并使用 gem active_elastic_job

我们有一个这样定义的工作:

class MyJob < ActiveJob::Base
  rescue_from(StandardError) do |exception|
    self.class.set(:wait => 1.minutes).perform_later
  end

  def perform
    MyLongTask.run
  end
end

我们体验到,当工作环境中的一个实例被杀死(由于自动缩放或其他原因)时,rescue_from 不会被执行并且作业不会被发送回队列。

我们如何捕获实例被调用以终止的那一刻,以便我们可以在我的进程真正终止之前优雅地做出反应并结束? (如果可能的话)

更新

我正在尝试这个

class MyJob < ActiveJob::Base
  def perform
    begin
      sleep(100)
    rescue SignalException => e
      # send signal to some log place
      raise e
    end
  end
end

但是,当我使用$ restart puma 终止 puma 进程时,终止实例也不会发送日志

【问题讨论】:

  • 你使用什么 gem 作为活动的工作后端?
  • 这可能是一个棘手的问题。在理想情况下,运行您的作业的进程将收到终止信号并决定执行以下操作:如果您的作业没有及时完成,它只会“返回”队列。例如,这是 sidekiq 模型。在您的特定情况下,将信号捕获在 Web 应用程序进程本身中可能是一种(以某种方式设计的)解决方案。但是你需要一些机制来重新排队你的工作。我会考虑的……
  • @RicardoValeriano ActiveJobs 有一个机制来重新排队工作 self.perform_later 但我首先必须捕获信号,但我仍然不知道如何
  • 您是否尝试过从 Exception 而不是 StandardError 进行救援,因为它可能会导致不同的异常

标签: ruby-on-rails amazon-web-services amazon-sqs rails-activejob amazon-elastic-beanstalk


【解决方案1】:

通过捕获SIGTERM 信号,您可以在进程终止之前执行您想要的任何清理(您的环境可能稍后会发送一个无法捕获的SIGKILL)。

Signal.trap(:SIGTERM) {
  # perform cleanup here
  exit
}

【讨论】:

  • 如何在 Rails + ActiveJob 环境中注册?
  • 我正在尝试rescue SignalException,正如您在我的问题更新中看到的那样,但它不起作用
  • 在全局级别注册信号处理程序,作为初始化的一部分。 Signalruby 的一部分,而不是 rails
最近更新 更多