Reputation: 349
I have a Ruby application running with Puma. Now I wanted to add a websocket to broadcast REST requests to the connected clients. I managed to create a websocket server with em-websocket gem just by adding some code in my config.ru:
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
The problem now is that when I run 'rails server -b 0.0.0.0' the websocket is running but my application is not. When connecting to localhost:3000 I get a time out. What can I do to run them together?
Follow up question: How can I broadcast over the websocket to the connected clients? I thought about adding to the controller of the REST requests a broadcast method. Is that possible?
Upvotes: 0
Views: 534
Reputation: 19221
To have both the Rails HTTP and the Websocket service share the same port you have two options that I know of:
You can setup a proxy that uses that port (perhaps nginx) and forwards each request to it's respective app-server (i.e. Puma and EM).
You can use a Websocket+HTTP server and run Websockets services as middleware within your HTTP (Rails) app (i.e., using ActionCable, Faye or iodine
+plezi
).
I'm assuming the second solution is more accommodating, though it will require that you port your code from em-websockets
to some other solution (i.e. Faye or Iodine/Plezi).
I should note that benchmarks show that em-websocket
might break down under stress, over-exhausting the CPU.
I'm Iodine's author, so I'm biased and I believe it's a better solution than most Ruby alternatives (and some benchmarks agree). Iodine leverages the proposed (and probably abandoned) Rack-Websocket specification, so the HTTP and Websocket connections share the same server and IO reactor, allowing for better resource management.
However, you can also use Faye, which (similar to the current ActionCable implementation) hijacks the socket from the HTTP server and attaches it to a separate IO reactor after establishing a Websocket connection.
Upvotes: 2