gpt4 book ai didi

ruby-on-rails - 如何优雅地重新启动 delay_job 消费者?

转载 作者:行者123 更新时间:2023-12-04 12:32:31 35 4
gpt4 key购买 nike

我想知道在新代码推送后优雅地重新启动 delay_job 消费者的最佳方法是什么?我正在使用 capistrano 推送代码,并且我知道有一些命令可以重新启动,但是如果当前有作业正在运行,则该命令要么挂起(并且我的部署需要永远执行),要么强制退出当前正在运行的作业并且我会丢失数据。

理想情况下,我希望我的部署像这样发生:

  • 现有的 delay_job 使用者正在使用版本 1 代码运行
  • 我跑 cap deploy并将版本 2 代码推送到新服务器
  • 在部署期间,我们触摸一个文件来告诉 delay_job 在处理完当前作业后重新启动。这可以通过多种不同的方式完成,但我认为这类似于如何优雅地重新启动乘客
  • 现有的delayed_job 消费者使用版本1 代码继续完成当前工作
  • 当前作业完成,delayed_job 消费者看到它需要重新启动才能继续处理作业
  • delay_job 消费者自动重启,现在运行版本 2 代码
  • delay_job 消费者继续处理作业,现在在版本 2 代码上运行

  • 我试图通过检查代码的当前修订版在作业运行之前插入一些代码以重新启动,但每次我这样做时,它都会死掉,实际上并没有重新启动任何东西。示例代码如下:
    def before(job)
    # check to make sure that the version of code here is the right version of code
    live_git_hash = LIVE_REVISION
    local_git_hash = LOCAL_REVISION

    if live_git_hash != local_git_hash
    # get environment to reload in
    environment = Rails.env # production, development, staging

    # restart the delayed job system
    %x("export RAILS_ENV=#{environment} && ./script/delayed_job restart")
    end
    end

    它可以很好地检测到它,但它在 shell 调用中死亡。有任何想法吗?

    谢谢!

    最佳答案

    想出了一个有效的解决方案。

    我有一个基类,我所有的延迟作业都继承自该基类,名为 BaseJob :

    class BaseJob
    attr_accessor :live_hash

    def before(job)
    # check to make sure that the version of code here is the right version of code
    resp = HTTParty.get("#{Rails.application.config.root_url}/revision")
    self.live_hash = resp.body.strip
    end

    def should_perform()
    return self.live_hash == GIT_REVISION
    end

    def perform()
    if self.should_perform == true
    self.safe_perform()
    end
    end

    def safe_perform()
    # override this method in subclasses
    end

    def success(job)
    if self.should_perform == false
    # log stats here about a failure

    # enqueue a new job of the same kind
    new_job = DelayedJob.new
    new_job.priority = job.priority
    new_job.handler = job.handler
    new_job.queue = job.queue
    new_job.run_at = job.run_at
    new_job.save
    job.delete

    # restart the delayed job system
    %x("export RAILS_ENV=#{Rails.env} && ./script/delayed_job stop")
    else
    # log stats here about a success
    end
    end

    end

    所有基类都继承自 BaseJob并覆盖 safe_perform真正做他们的工作。关于上述代码的一些假设:
  • Rails.application.config.root_url指向您的应用程序的根目录(即:www.myapp.com)
  • 暴露了一条路由,叫/revision (即:www.myapp.com/revision)
  • 有一个名为 GIT_REVISION 的全局常量您的应用知道

  • 我最终做的是输入 git rev-parse HEAD 的输出在一个文件中并用代码推送它。它会在启动时加载,因此它可以在 web 版本以及 delay_job 消费者中使用。

    当我们通过 Capistrano 部署代码时,我们不再停止、启动或重新启动 delay_job 消费者。我们在每分钟运行一次的消费者节点上安装一个 cronjob,并确定 delay_job 进程是否正在运行。如果不是,则会产生一个新的。

    由于所有这些,满足以下所有条件:
  • 推送代码不再等待 delay_job 重新启动/强制终止。推送新代码时,正在运行的现有作业将保持不变。
  • 如果消费者正在运行旧代码,我们可以检测到作业何时开始。工作重新排队,消费者自杀。
  • 当一个 delay_job 死掉时,一个新的会通过一个带有新代码的 cronjob 产生(根据启动 delay_job 的性质,它有新代码)。
  • 如果您对杀死 delay_job 消费者感到偏执,请安装一个 nagios 检查,它与 cron 作业执行相同的操作,但在 delay_job 进程未运行 5 分钟时提醒您。
  • 关于ruby-on-rails - 如何优雅地重新启动 delay_job 消费者?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19866896/

    35 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com