【问题标题】:Faye ruby client publishing only onceFaye ruby​​ 客户端仅发布一次
【发布时间】:2014-09-16 12:15:20
【问题描述】:

我有一个在 localhost 上运行的 faye 服务器 (nodejs),我正在尝试设置一个需要定期在服务器上发布的服务器端 ruby​​ 客户端。这是我尝试使用的代码。 (请忽略开头的注释代码)。
我创建了一个类变量@@client,并在类加载后立即对其进行初始化。我定义了一个类方法pub,它的任务是在faye服务器上发布一些东西。
最后,我只调用了两次pub 方法。成功接收到第一个发布回调,但第二个发布未生成callbackerrback。由于没有将控制权交还给应用程序,因此应用程序只是挂在那里。
如果我将 gobal 变量设为 $client(当前已评论),则行为是相同的。但是,如果我每次调用 pub 时都创建客户端,那么发布就会顺利进行。我在EM.run 循环或外部启动它,行为是相同的。 (如预期)

我不想每次我想发布一些东西时都建立新的连接,因为这违背了目的。另外,如果我每次调用该方法时都在EM.run 中创建一个新客户端,则客户端连接不会自行关闭。我可以看到它们在lsof 命令中作为打开文件打开,很快我就会开始收到too many open files 错误。

我对事件机器的理解并不正确,也许我在那里遗漏了一些东西。

require 'faye'
require 'eventmachine'

# $client = Faye::Client.new('http://localhost:5050/faye')
class Fayeclient
  puts "#{__LINE__}: Reactor running: " + EM.reactor_running?.to_s

  # if !defined? @@client or @@client.nil?
    @@client = Faye::Client.new('http://localhost:5050/faye')
    puts "Created client: " + @@client.inspect
  # end

  def self.pub
    puts "#{__LINE__}: Reactor running: " + EM.reactor_running?.to_s
    # client = Faye::Client.new('http://localhost:5050/faye') #$client
    # client = @@client
    EM.run {
      #client = Faye::Client.new('http://localhost:5050/faye') #$client
      puts "#{__LINE__}: Reactor running: " + EM.reactor_running?.to_s
      puts @@client.inspect

      publication = @@client.publish('/foo', 'text' =>'Hello world')
      puts "Publishing: #{publication.inspect}"
      # puts "Publication methods: #{publication.methods}"

      publication.callback do
        puts "Did it #{publication.inspect}"
        EM.stop_event_loop
        puts "#{__LINE__}: Reactor running: " + EM.reactor_running?.to_s
        # puts "#{client.methods}"
#        puts client.inspect
#        client.remove_all_listeners
#        puts client.inspect
      end
      publication.errback do |error |
          puts error.inspect
          EM.stop_event_loop
      end
    }
    puts "Outside event loop"
    puts "#{__LINE__}: Reactor running: " + EM.reactor_running?.to_s
  end
end

Fayeclient.pub
Fayeclient.pub

【问题讨论】:

  • 我无法具体帮助您,但您可能想查看github.com/ryanb/private_pub。它具有更高级别的安全通道,完全在 Ruby 中完成。

标签: ruby websocket eventmachine faye


【解决方案1】:

EM.run 调用是阻塞的,你必须在一个单独的线程上运行它,并在一切结束后最终加入它。在示例中,我使用的是Singleton,但这取决于您。

这可以正确完成 2 个 faye 电话。

#!/usr/bin/env ruby
#
require 'faye'
require 'singleton'
require 'eventmachine'


class Fayeclient
  include Singleton
  attr_accessor :em_thread, :client

  def initialize
    self.em_thread = Thread.new do
      EM.run
    end
    self.client = Faye::Client.new('http://localhost:8890/faye')
  end

  def pub
    puts "#{__LINE__}: Reactor running: " + EM.reactor_running?.to_s
    puts client.inspect

    publication = client.publish('/foo', 'text' =>'Hello world')
    puts "Publishing: #{publication.inspect}"

    publication.callback do
      puts "Did it #{publication.inspect}"
      EM.stop_event_loop
      puts "#{__LINE__}: Reactor running: " + EM.reactor_running?.to_s
    end
    publication.errback do |error |
        puts error.inspect
        EM.stop_event_loop
    end
  end
end

Fayeclient.instance.pub
Fayeclient.instance.pub

Fayeclient.instance.em_thread.join

以我个人的经验,无论如何,必须在 Rails 应用程序中处理 EventMachine 可能会一团糟,一些网络服务器使用 EM,而另一些则没有,当您想从控制台进行测试时,它可能无法按预期工作。

我的解决方案是回退到 http 调用:

RestClient.post "http://localhost:#{Rails.configuration.faye_port}/faye", message: {foo: 'bar'}.to_json

如果您不需要从这段代码接收消息,我发现此解决方案更简单且易于自定义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-11
    • 1970-01-01
    • 1970-01-01
    • 2020-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多