新手问题 [已解决] 求助,Sidekiq Default Queue 任务莫名消失

yue · 2015年10月29日 · 最后由 yue 回复于 2015年10月30日 · 3886 次阅读

问题: 假设创建 7 个同样任务,都是 30 秒后执行,但是最终不是全部执行,可能只执行 5 个,不一定。

Debug:

  1. 查看 web UI,可以看到 7 个任务都成功进入列队。
  2. 查看 log,却只有部分的任务被执行了。其他莫名其妙的就消失了。
  3. Google, 因为 sidekiq/testing 导致了冲突 文档链接。 (但是这个原因被排除)
  4. 本地开发环境下任务全部完成,但是 staging/production 会有遗失现象。
  5. 本地 redis 版本是 2.8.17,服务器版本是 2.8.4 (查看 redis release log 没看到问题,同时任务插入没有问题,可以排除版本问题)

debug 很久都没有结果,请问大家有没有碰到过。

以下是其他信息:

#Gemfile
gem 'sidekiq', '3.4.2', require: ['sidekiq', 'sidekiq/web']
gem 'sidekiq-failures'
gem 'sidetiq'
gem 'redis'
group :development do
  gem 'capistrano-sidekiq'
end

group :test do
  gem 'rspec-sidekiq'
end
#sidekiq.yml 配置文件
:concurrency: 5
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log 
:queues:
    - default
development:
  :verbose: true
  :concurrency: 5
staging:
  :concurrency: 10
production:
  :concurrency: 20
# config/initializers/sidekiq.rb
Sidekiq::Web.use Rack::Session::Cookie, :secret => "SOMETHING SECRET"
Sidekiq::Web.instance_eval { @middleware.reverse! } # Last added, First Run

Sidekiq.configure_server do |config|
  config.redis = { url: 'redis://localhost:6379/12' }
end

Sidekiq.configure_client do |config|
  config.redis = { url: 'redis://localhost:6379/12' }
end

Sidekiq::Web.use(Rack::Auth::Basic) do |user, password|
  [user, password] == ["", ""]
end
#调用代码
def create_qr_codes
  logger.info "#{Time.now}, invoke create_qr_codes"
  QRCodeWorker.perform_in(30.seconds, object_id)
end

class QRCodeWorker
  include Sidekiq::Worker
  sidekiq_options :retry => 1

  def perform(id)
    # do hard work
  end
end

解决方法 问题出在了服务器上同时跑了多个 sidekiq 的 instances,但是没有设置 namespace。修改如下:

# config/initializers/sidekiq.rb
# 旧的配置,没有 namespace
Sidekiq.configure_server do |config|
  config.redis = { url: 'redis://localhost:6379/12' }
end

Sidekiq.configure_client do |config|
  config.redis = { url: 'redis://localhost:6379/12' }
end

# 新的配置,有 namespace
Sidekiq.configure_server do |config|
  config.redis = { url: 'redis://localhost:6379/12', namespace: 'your namespace' }
end

Sidekiq.configure_client do |config|
  config.redis = { url: 'redis://localhost:6379/12', namespace: 'your namespace'  }
end

这样就可以了。吃一堑长一智。

查查日志呢?

#1 楼 @cassiuschen 查了。不执行的任务没有日志记录。

redis-server 的配置是怎样的,如果被配置成 LRU cache 模式在内存满了的时候是会丢失信息的。

如果不是这个原因的话,还可以进一步确认一下,丢失的 job 相关的内容是仍然存在 redis 里面还是被 sidekiq worker 消费掉了。

检查了那些文件日志?

#3 楼 @hooopo #4 楼 @blogbin 已经找到原因。服务器上跑了多个 sidekiq instances,没有设置 namespace,导致 job 丢失。 https://github.com/mperham/sidekiq/wiki/Problems-and-Troubleshooting 真是没注意,花了很多时间 debug。:(

#5 楼 @yue 作者不再推荐用 redis namespace 隔离,应该用 Database 或者 Instances https://github.com/mperham/sidekiq/blob/master/4.0-Upgrade.md

#5 楼 @yue 被其他 instances 执行了的话,难道不会在那些 instances 里边触发异常吗?比如找不到类定义之类的。我们现在都是用 database 隔离,不同应用就用不同的 database,从根本上解决问题哈。

#7 楼 @martin91 database 隔离的方法看起。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号