nee*_*raj 4 ruby eventmachine websocket faye
我有一个在localhost上运行的faye服务器(nodejs),我正在尝试设置一个服务器端ruby客户端,它需要定期在服务器上发布.这是我试图使用的代码.(请忽略开头的评论代码).
我创建一个类变量,@@client并在类加载后立即初始化它.我定义了一个类方法,pub其任务是在faye服务器上发布一些东西.
最后,我只是调用该pub方法两次.第一个发布回调被成功收到,但第二个出版物没有成功callback或者errback.由于控件尚未返回给应用程序,因此该应用程序就会挂起.
如果我创建gobal变量$client(当前已注释),行为是相同的.但是,如果我每次pub 都调用客户端,那么发布会顺利进行.我在EM.run循环或外部启动它,行为是相同的.(如预期的那样)
每次我想发布一些东西都不想建立新的连接,因为这会破坏目的.此外,如果我在EM.run每次调用方法时创建一个新客户端,则客户端连接不会自行关闭.我可以看到它们lsof作为打开文件在命令中打开,很快我就会开始收到too many open files错误.
我没有真正理解Event Machine,也许我错过了那里的东西.
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
Run Code Online (Sandbox Code Playgroud)
EM.runcall是阻塞的,你必须在一个单独的线程上运行它,并在最终结束时最终加入它.在示例中,我使用的是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
Run Code Online (Sandbox Code Playgroud)
根据我的个人经验,无论如何,不得不在Rails应用程序中处理EventMachine可能是一团糟,一些Web服务器使用EM,其他情况则不然,当您想要从控制台进行测试时,它可能无法按预期工作.
我的解决方案是回退到http调用:
RestClient.post "http://localhost:#{Rails.configuration.faye_port}/faye", message: {foo: 'bar'}.to_json
Run Code Online (Sandbox Code Playgroud)
如果您不需要从这段代码接收消息,我发现这个解决方案更简单,更容易定制.