跟随
Redis Pub/Sub
这工作正常,我可以发布消息在任何类使用
$redis.publish 'channel',{ object: @object.id }
使用redis-cli> MONITOR,我可以验证这个请求是否正确发布
[0 127.0.0.1:64192] "publish" "channel" "{:object=>\"5331d541f4eec77185000003\" }"
当我在其他类(侦听器类)中为该通道添加订阅者块时,问题开始,如下所示
class OtherClass $redis.subscribe('channel') do |payload| p payload end end
[0 127.0.0.1:52930] "subscribe" "channel"
问题是当我将用户侦听器类添加到相同的rails应用程序…它停止工作,因为OtherClass侦听redis服务器并停止执行任何其他代码…它只是坐在那里听.
所以有一种方法可以在同一个轨道应用程序上使用redis制作消息总线,以便事件从某些类或服务对象发布,并且有特定通道的监听器可以在后台接收事件时采取行动.
我知道我可能会使用sidekiq或任何其他背景工作人员来完成这项工作,但过了一会儿后台工作人员变得凌乱而且不可维护.
解决方法
Redis#subscribe的实现是
a loop,它将控制当前线程以便收听事件.这意味着当您按照您显示的方式将订阅放入Rails类的上下文中时,引导过程将停止.
您可以尝试在线程中包装调用,但是这种方法将在每次此类加载到新进程(如rails控制台或多个独角兽)时创建一个新的订阅.另外,你必须要注意共享状态和其他线程问题.这可能不是你想要的
您最好开始加载rails环境的不同进程,并与提供Web请求的进程分开订阅redis.这可能是一个如下的耙子任务:
namespace :subscribe do task :redis => :environment do $redis.subscribe("bravo") do |on| on.message do |channel,message| Rails.logger.info("Broadcast on channel #{channel}: #{message}") OtherClass.some_method # yada yada end end end end