一尘不染

Redis发布/订阅在轨道上

redis

跟随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

中的redis-cli > MONITOR,还表明侦听器已正确订阅

[0 127.0.0.1:52930] "subscribe" "channel"

问题是,当我将订户侦听器类添加到相同的Rails应用程序时…它停止工作,导致OtherClass侦听Redis服务器并停止执行任何其他代码…它只是坐在那里侦听。

因此,有一种方法可以在同一个Rails应用程序上使用redis制作消息总线…以便
从某些类或服务对象发布事件,并且有特定通道的侦听器在后台接收事件时起作用。

我知道我可能会使用sidekiq或任何其他背景工作人员来完成这项工作…但是过了一会儿,背景工作人员变得凌乱且难以维护。


阅读 279

收藏
2020-06-20

共1个答案

一尘不染

的实现Redis#subscribe一个循环,它将采取对当前线程的控制以侦听事件。这意味着,当按照您显示的方式将订阅拖放到Rails类的上下文中时,引导过程将停止。

您可以尝试将调用包装在线程中,但是这种方法将在每次将该类加载到新进程(如Rails控制台或多个独角兽)中时,实际上都会创建一个新的订阅。另外,您必须注意共享状态和其他线程问题。这可能不是您想要的。

最好启动一个不同的进程来加载Rails环境并与服务Web请求的进程分开预订Redis。可能是类似以下的rake任务:

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
2020-06-20