下午好,
我有两个单独的但相关的应用程序。它们都应具有自己的后台队列 (请参阅:独立的Sidekiq和Redis进程) 。但是,我偶尔希望能够将作业app2从推送到的队列中app1。
app2
app1
从简单的队列/推送角度来看,如果app1没有现有的Sidekiq / Redis堆栈,则很容易做到这一点:
# In a process, far far away # Configure client Sidekiq.configure_client do |config| config.redis = { :url => 'redis://redis.example.com:7372/12', :namespace => 'mynamespace' } end # Push jobs without class definition Sidekiq::Client.push('class' => 'Example::Workers::Trace', 'args' => ['hello!']) # Push jobs overriding default's Sidekiq::Client.push('queue' => 'example', 'retry' => 3, 'class' => 'Example::Workers::Trace', 'args' => ['hello!'])
但是,考虑到我本来会调用a Sidekiq.configure_client和Sidekiq.configure_serverfrom app1,那么在这之间可能需要一步。
Sidekiq.configure_client
Sidekiq.configure_server
显然,我可以直接从Sidekiq内部获取序列化和规范化代码,然后手动将其推送到app2的redis队列中,但这似乎是一种脆弱的解决方案。我希望能够使用该Client.push功能。
Client.push
我想理想的解决方案是:
SidekiqTWO.configure_client { remote connection..... } SidekiqTWO::Client.push(job....)
SidekiqTWO.configure_client { remote connection..... }
SidekiqTWO::Client.push(job....)
甚至:
$redis_remote = remote_connection.....
Sidekiq::Client.push(job, $redis_remote)
显然有点滑稽,但这是我理想的用例。
谢谢!
因此,有一件事是,根据FAQ,“ Sidekiq消息格式非常简单且 稳定 :它只是JSON格式的哈希”。强调我的想法- 我认为将JSON发送到sidekiq并不容易。尤其是当您想要精细地控制将作业发送到哪个Redis实例时(例如在OP的情况下),我可能只需要编写一个小的包装即可让我指示Redis实例以及要排队的作业。
对于凯文·比德尔的更普遍的情况,循环作业到Redis的情况下,我想你 不要 它希望有控制的Redis实例used– 你只是想排队,并有分布自动管理。到目前为止,似乎只有一个人要求这样做,他们提出了一个使用Redis::Distributed以下解决方案的解决方案:
Redis::Distributed
datastore_config = YAML.load(ERB.new(File.read(File.join(Rails.root, "config", "redis.yml"))).result) datastore_config = datastore_config["defaults"].merge(datastore_config[::Rails.env]) if datastore_config[:host].is_a?(Array) if datastore_config[:host].length == 1 datastore_config[:host] = datastore_config[:host].first else datastore_config = datastore_config[:host].map do |host| host_has_port = host =~ /:\d+\z/ if host_has_port "redis://#{host}/#{datastore_config[:db] || 0}" else "redis://#{host}:#{datastore_config[:port] || 6379}/#{datastore_config[:db] || 0}" end end end end Sidekiq.configure_server do |config| config.redis = ::ConnectionPool.new(:size => Sidekiq.options[:concurrency] + 2, :timeout => 2) do redis = if datastore_config.is_a? Array Redis::Distributed.new(datastore_config) else Redis.new(datastore_config) end Redis::Namespace.new('resque', :redis => redis) end end
另一件事是在你的追求考虑,以获得高可用性和故障转移是让Sidekiq专业,其中包括可靠性的特点:“该Sidekiq专业客户能承受瞬时Redis的中断将本地排队工作时的错误,并尝试提供这些就业机会。连接恢复后。” 由于sidekiq始终用于后台进程,因此,如果Redis实例发生故障,则短暂的延迟不会影响您的应用程序。如果您的两个Redis实例之一发生故障并且正在使用轮询,则除非使用此功能,否则您仍然会丢失一些工作。