【问题标题】:How to kick off pubsub subscriber in Rails app如何在 Rails 应用程序中启动 pubsub 订阅者
【发布时间】:2013-05-18 01:15:12
【问题描述】:

我有一个 Rails (web) 应用程序,我还需要添加一个 (redis) pub/sub 订阅者。

下面是我需要启动的 PubsubSubscriber 类,然后应用程序启动。

redis 连接是在 resque.rb 初始化文件中创建的。我在连接后尝试了 PubsubSubscriber.new,但是当我尝试启动 rails 服务器时,它挂在:

=> Booting Thin
=> Rails 3.2.13 application starting in development on http://0.0.0.0:5000
=> Call with -d to detach
=> Ctrl-C to shutdown server

与服务器启动成功时相反:

=> Booting Thin
=> Rails 3.2.13 application starting in development on http://0.0.0.0:5000
=> Call with -d to detach
=> Ctrl-C to shutdown server
>> Thin web server (v1.5.1 codename Straight Razor)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:5000, CTRL+C to stop

知道为什么当我尝试在初始化程序中实例化 PubsubSubscriber 类时服务器会挂起吗?有更好的起点吗?


# example modified from https://github.com/redis/redis-rb/blob/master/examples/pubsub.rb
class PubsubSubscriber

  def initialize
    $redis.psubscribe( :channel_one ) do |on|

      on.psubscribe do |event, total|
      end

      on.pmessage do |pattern, event, message|
        # message received, kick off some workers
      end

      on.punsubscribe do |event, total|
      end

    end

 end
end

【问题讨论】:

  • 这很正常,订阅调用会“永远”阻塞;您应该使用 eventmachine 之类的东西或在不同的进程/线程中运行它
  • 我正在使用 Thin,这听起来像是句柄对我来说是 EM 的东西,所以我不需要明确的 EM.run 调用。我试过 Thread.new { PubsubSubscriber.new } 但这也是阻塞的。有什么建议吗?
  • 一个对象的构造函数不是用来做阻塞事件的地方,甚至做任何其他事情,比如运行查询等等。它应该只用于初始化一个对象。如果 Ruby 对象系统正在等待构造函数完成以便正确创建对象,我不会感到惊讶。所以试着把它移到构造函数之外,放到像start这样的单独方法中,然后像Thread.new { PubsubSubscriber.new.start }一样运行它

标签: ruby-on-rails ruby redis publish-subscribe


【解决方案1】:

您遇到的一个问题是,当您在初始化程序中时,EventMachine 尚未准备好。因此,将您的初始化包装在 EM.next_tick 中会延迟您的代码,直到 EventMachine 准备好:

EM.next_tick { ... EventMachine code here ... }

当我尝试这个时,我的服务器一直启动......然后在调用 $redis.psubscribe 时被阻止。

但是,切换到 em-hiredis 有效:

# config/initializers/redis_pubsub.rb
EM.next_tick do
  $emredis = EM::Hiredis.connect(uri)

  $emredis.pubsub.subscribe('channelone') do |message|
    Rails.logger.debug message
  end
end  

发生这种情况是因为标准的 redis gem 没有通过 EventMachine 接口监听事件——它只是创建一个到你的 redis 服务器的连接,然后阻塞其他一切。

为了利用 EM,您需要建立一个简单的连接,其形式为:

class RedisConnection
    # connect to redis
    def connect(host, port)
      EventMachine.connect host, port, self
    end

    def post_init
      # send subscribe channel_one to redis    
    end

    def receive_data(data)
      # channel_one messages will arrive here
    end
end

我在这个要点中有一个工作示例:https://gist.github.com/wheeyls/5647713

em-hiredis是使用该接口的redis客户端。

【讨论】:

    猜你喜欢
    • 2021-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-10
    • 2019-09-21
    • 2021-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多