如何以编程方式在 rails 中 start/stop heroku workers?

How to programmatically start/stop heroku workers in rails?

大约 6 年前,有一个 rails gem caled HireFire,它与后台作业一起根据需要启动和停止工作人员,因此工作人员并不总是 运行 和一直在累积费用。

HireFire 似乎已经不存在了(作为 gem),我想知道这些天如何自动缩放 heroku workers?

我不想为此支付服务费用。

我环顾四周,惊讶地发现解决方案似乎并不明显。

heroku 是否实现了这种类型的自动缩放,或者是否有另一个 rails gem 可以为我做到这一点?谢谢

您可以使用 CLI 扩展 Heroku dynos,因此构建您自己的服务来执行此操作非常简单。

创建另一个使用调度程序 运行 每小时的应用程序,使用 unix shell 脚本下载和安装 CLI,并使用存储为 ENV 变量的凭据发送 scale 命令到其他应用程序。

这里有一个代码库作为该技术的示例:https://github.com/kbaum/heroku-database-backups

更新:我找不到现有的 library/gem/plugin 来帮我解决这个问题,所以我决定尝试自己解决。

我决定在想出解决方案后post回到这里。也许对其他人有帮助。

DelayedJob 有一个插件系统(我必须将我的 gem 版本升级到最新版本)

这是我写的插件。我不认为它会赢得美貌奖,但它似乎可以解决问题。如果我做错了什么,请 post 发表评论。

我也做到了,所以它会检查 production/development env 并在开发时运行本地 DelayedJob 脚本。

class HerokuWorkerDelayedJobPlugin < Delayed::Plugin
  callbacks do |lifecycle|
    lifecycle.before(:enqueue) do |job, *args, &block|
      Rails.logger.info "----before enqueue -----"
      self.start
    end

    lifecycle.after(:enqueue) do |job, *args, &block|
      Rails.logger.info "----after enqueue -----"
    end

    lifecycle.after(:invoke_job) do |job, *args, &block|
      Rails.logger.info "----after invoke_job -----"
    end

    lifecycle.after(:perform) do |worker, job, *args, &block|
      Rails.logger.info "----after perform-----"
      self.stop
    end

    def self.start
      if Rails.env.production?
        self.set_heroku_workers 1
      else
        `script/delayed_job start`
      end
    end

    def self.stop
      if Rails.env.production?
        self.set_heroku_workers 0
      else
        `script/delayed_job stop`
      end
    end

    def self.set_heroku_workers(num)
      heroku = PlatformAPI.connect_oauth(ENV['PLATFORM_API_OAUTH_TOKEN'])  #https://github.com/heroku/platform-api
      heroku.formation.update('my-app', 'worker', {quantity:   num}) #https://devcenter.heroku.com/articles/platform-api-reference#formation
    end
  end
end

您需要在初始化程序中像这样将插件添加到 DelayedJob:

Delayed::Worker.plugins << HerokuWorkerDelayedJobPlugin

截至 2019 年,Heroku gem 已落伍。所以改用网络api。就我而言,我使用了 rest-client。可以使用

从 heroku cli 检索授权凭据

heroku authorizations:create

          if Rails.env.production?
            response = RestClient::Request.execute(
            method: :delete,
            url: 'https://api.heroku.com/apps/yourappname/dynos/worker.1',
            headers: {Authorization: 'Bearer xxxx-xxx-xxx-xxx-xxxxx',accept:'application/vnd.heroku+json; version=3'}
            )   
          end