如何使用Ruby连接多个WebSockets?

时间:2017-02-28 12:20:57

标签: ruby websocket eventmachine

使用faye-websocket和EventMachine,代码与faye-websocket的客户端示例非常相似:

require 'faye/websocket'
require 'eventmachine'

def setup_socket(url)
    EM.run {
      ws = Faye::WebSocket::Client.new(url)

      ws.on :open do ... end

      ws.on :message do ... end

      ws.on :close do ... end
    }
end

我希望并行打开多个连接。由于执行不会退出setup_socket子句,因此我无法多次调用EM.run。我尝试在不同的主题中多次运行setup_socket

urls.each do |url|
    Thread.new { setup_socket(url) }
end

但由于puts语句无法达到输出,因此似乎没有做任何事情。

我不限于使用faye-websocket,但似乎大多数人都使用这个库。如果可能的话,我想避免多线程。我也不想失去改变的可能性(例如添加新的websocket)。因此,不希望在EM.run子句中移动URL的迭代,而是启动多个EM会更有益。我以一种非常干净的方式找到了example for starting multiple servers via EM。我正在寻找类似的东西。

如何同时连接多个WebSockets?

2 个答案:

答案 0 :(得分:2)

这是一种方法。

首先,您必须接受EM线程需要运行。没有这个线程,您将无法处理任何当前连接。所以你无法解决这个问题。

然后,为了向EM线程添加新URL,您需要一些方法从主线程到EM线程进行通信,因此您可以告诉它启动新连接。这可以使用EventMachine::Channel完成。

所以我们现在可以建立的是这样的:

@channel = EventMachine::Channel.new

Thread.new {
  EventMachine.run {
     @channel.subscribe { |url| 
       ws = Faye::...new(url)
       ...
    }
  }
}

然后在主线程中,只要你想在事件循环中添加新的URL,就可以使用它:

def setup_socket(url)
  @channel.push(url)
end

答案 1 :(得分:0)

以下是另一种方法...使用Iodine的原生websocket支持(或Plezi framework)代替em-websocket ......

......我有偏见(我是作者),但我认为他们让事情变得容易多了。此外,Plezi提供Redis自动缩放功能,因此很容易实现。

这是一个使用Plezi的例子,其中每个Controller都像一个频道,它有自己的URL和Websocket回调(尽管我认为Plezi的自动调度比下层更容易on_message回调)。此代码可以放在config.ru文件中:

require 'plezi'

# Once controller / channel for all members of the "Red" group
class RedGroup
  def index # HTTP index for the /red URL
    "return the RedGroup client using `:render`".freeze
  end
  # handle websocket messages
  def on_message data
    # in this example, we'll send the data to all the members of the other group.
    BlueGroup.broadcast :handle_message, data
  end
  # This is the method activated by the "broadcast" message
  def handle_message data
    write data # write the data to the client.
  end
end
# the blue group controller / channel
class BlueGroup
  def index # HTTP index for the /blue URL
    "return the BlueGroup client using `:render`".freeze
  end
  # handle websocket messages
  def on_message data
    # in this example, we'll send the data to all the members of the other group.
    RedGroup.broadcast :handle_message, data
  end
  # This is the method activated by the "broadcast" message
  def handle_message data
    write data
  end
end
# the routes
Plezi.route '/red', RedGroup
Plezi.route '/blue', BlueGroup
# Set the Rack application
run Plezi.app

P.S。

我也写了这个答案,因为在某些情况下em-websocket可能会失败或占用资源。我不确定详细信息,但在websocket-shootout benchmarkAnyCable Websocket Benchmarks都注意到了。