You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dokku部署后未完成任务的Worker被移除问题求助

解决Dokku部署Rails应用时Worker任务中断问题

方案一:让旧Worker完成任务后再终止(优雅关闭)

  • 配置Worker框架的优雅关闭超时:如果使用Sidekiq这类主流Worker框架,在config/initializers/sidekiq.rb中添加超时配置,让Worker收到终止信号后,先处理完当前任务再退出:
    Sidekiq.configure_server do |config|
      config.shutdown_timeout = 300 # 等待5分钟,可根据任务实际时长调整
    end
    
    自定义Worker需自行实现信号捕获逻辑:捕获TERM信号后,停止接收新任务,待当前所有任务执行完毕再退出进程。
  • 调整Dokku的进程停止超时:通过Dokku配置给旧Worker足够的处理时间,避免被强制杀掉:
    dokku config:set YOUR_APP_NAME DOKKU_PROCESS_STOP_TIMEOUT=300
    

方案二:让新Worker承接未完成任务(任务持久化+幂等性)

  • 确保任务持久化到外部存储:不要将任务存在Worker实例本地,使用Redis、数据库等外部存储(比如Sidekiq默认用Redis),部署后新Worker连接同一存储即可获取未完成任务。
  • 实现任务幂等性:即使任务被重复执行也不会产生异常结果。可以给每个任务添加唯一标识,执行前检查任务是否已处理:
    class MyWorker
      include Sidekiq::Worker
      sidekiq_options unique: :until_executed
    
      def perform(task_id)
        return if Task.find(task_id).completed?
        # 执行任务逻辑
        Task.find(task_id).update!(completed: true)
      end
    end
    
  • 开启任务重试机制:在Worker配置中启用重试,中断的任务会自动重新入队,由新Worker接手处理:
    class MyWorker
      include Sidekiq::Worker
      sidekiq_options retry: 3 # 重试3次,可按需调整
    end
    

方案三:调整Dokku部署策略

  • 使用滚动部署:让Dokku先启动新Worker,再逐步关闭旧Worker,保证任务处理不中断:
    dokku apps:set YOUR_APP_NAME DOKKU_DEPLOY_STRATEGY=rollout
    
  • 控制滚动部署的批次大小:如果有多个Worker实例,设置每次只替换一个实例,减少对任务队列的影响:
    dokku apps:set YOUR_APP_NAME DOKKU_ROLLOUT_BATCH_SIZE=1
    

内容的提问来源于stack exchange,提问作者Pimenta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 02:16:13