我有一个运行Puma的Ruby应用程序。现在我想添加一个websocket来向连接的客户端广播REST请求。我设法通过在我的config.ru中添加一些代码来创建一个带有em-websocket gem的websocket服务器:
require_relative 'config/environment'
require 'em-websocket'
Socket = EM.run {
@channel = EM::Channel.new
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 2929, :debug => true) do |ws|
ws.onopen {
sid = @channel.subscribe { |msg| ws.send msg }
@channel.push "#{sid} connected!"
ws.onmessage { |msg|
@channel.push "blubb"
}
ws.onclose {
@channel.unsubscribe(sid)
}
}
end
}
run Rails.application
现在的问题是,当我运行'rails server -b 0.0.0.0'时,websocket正在运行,但我的应用程序却没有。当连接到localhost:3000我有时间。 我可以做些什么来一起运行它们?
跟进问题:如何通过websocket广播到已连接的客户端?我想添加到REST的控制器请求广播方法。这可能吗?
答案 0 :(得分:0)
要让Rails HTTP和Websocket服务共享同一个端口,您有两个我知道的选项:
您可以设置使用该端口的代理(可能是nginx),并将每个请求转发给它的相应应用服务器(即Puma和EM)。
您可以使用Websocket + HTTP服务器并在HTTP(Rails)应用程序中运行Websockets服务作为中间件(即使用ActionCable,Faye或iodine
+ plezi
)。
我假设第二种解决方案更加宽松,但它需要您将代码从em-websockets
移植到其他解决方案(即Faye或Iodine / Plezi)。
我应该注意到基准显示em-websocket
might break down under stress, over-exhausting the CPU。
我是Iodine的作者,所以我有偏见,我相信这是一个比大多数Ruby替代品更好的解决方案(有些benchmarks同意)。 Iodine利用the proposed (and probably abandoned) Rack-Websocket specification,因此HTTP和Websocket连接共享相同的服务器和IO反应器,从而实现更好的资源管理。
但是,您也可以使用Faye(类似于当前的ActionCable实现)从HTTP服务器劫持套接字,并在建立Websocket连接后将其附加到单独的IO反应器。