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

Heroku生产环境Sidekiq Worker无法正常触发执行问题排查

问题描述

我在Rails 6应用中配置了ActiveRecord回调(after_create),预期在ProductsBatch记录每次创建时调用SyncProductsWorker(Sidekiq Worker)。该功能本地运行完全正常,但部署到Heroku生产环境后Worker始终不执行,哪怕在Heroku Rails控制台手动触发Worker、拿到了合法任务ID,日志里也没有对应执行记录,只有default队列的任务能正常运行。

相关代码

配置了after_create回调的ProductsBatch模型

module Imports
  class ProductsBatch < ImportsRecord
    attr_accessor :product_codes

    after_create :enqueue

    def enqueue
      ::Imports::SyncProductsWorker.perform_async(product_codes, self.id)
    end
  end
end

# 上述模型的基类
class ImportsRecord < ApplicationRecord
  self.abstract_class = true

  connects_to database: { writing: :imports }
end

SyncProductsWorker实现

module Imports
  class SyncProductsWorker
    include Sidekiq::Worker
    sidekiq_options queue: 'imports_sync'

    def perform(list, id)
      # 业务处理逻辑
    end
  end
end

Sidekiq配置

config/sidekiq.yml:

:max_retries: 16
:queues:
- default
- imports_sync
- imports_fetch_all
:dynamic: true

config/initializers/sidekiq.rb:

redis = { url: ENV['REDIS_URL'], ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } }

Sidekiq.configure_server do |config|
  config.redis = redis
end

Sidekiq.configure_client do |config|
  config.redis = redis
end

异常复现记录

Heroku Rails控制台手动调用Worker返回了任务ID:

heroku run rails console --app test-app                                                                      
 ›   Warning: heroku update available from 7.47.7 to 7.60.2.
Running rails console on ⬢ test-app... up, run.8489 (Hobby)
Loading production environment (Rails 6.1.4.1)
irb(main):013:0> ::Imports::SyncProductsWorker.perform_async(['11'], 10)
=> "5edf93e27fa2f41245587d49"

但Heroku日志中无该任务的任何执行记录,仅能看到default队列的任务日志:

2022-06-06T22:02:00.240650+00:00 app[worker.1]: [ActiveJob] [ProductAvailabilityAdjusterJob] [25c15f9d-e032-438e-bda2-16ffd557cc32] Performed ProductAvailabilityAdjusterJob (Job ID: 25c15f9d-e032-438e-bda2-16ffd557cc32) from Sidekiq(default) in 5.44ms
2022-06-06T22:02:00.240789+00:00 app[worker.1]: pid=4 tid=2xbk class=ProductAvailabilityAdjusterJob jid=91ad7e69e061df9f2f681ef3 elapsed=0.006 INFO: done

解决方案

核心原因是Heroku上启动的Sidekiq进程没有加载自定义队列配置,默认只监听default队列,投递到imports_sync队列的任务已经成功写入Redis,但没有进程消费,按以下步骤修复:

  • 修正Procfile中的Sidekiq启动命令,必须显式通过-C参数指定配置文件路径,否则生产环境Sidekiq不会自动读取config/sidekiq.yml。把worker启动行改为:
    worker: bundle exec sidekiq -C config/sidekiq.yml
    
    这是该场景下最高发的踩坑点:本地开发环境Rails会自动加载配置目录下的sidekiq.yml,但Heroku生产环境不会自动加载该文件,必须显式指定。
  • 重新部署后检查Sidekiq启动日志,确认启动日志里打印的监听队列列表包含imports_sync、imports_fetch_all,再测试任务执行即可。
  • 如果改完启动命令仍有问题,依次排查两点:
    1. 执行heroku ps --app 你的应用名确认worker dyno处于正常启动状态,Heroku默认不会自动开启worker dyno,很多人部署完只启动了web进程
    2. 确认web dyno和worker dyno的REDIS_URL环境变量值完全一致,避免客户端写入Redis、服务端连另一个Redis实例的情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 02:24:16