-
Notifications
You must be signed in to change notification settings - Fork 12
WebSockets guide
Rage Cable is an ActionCable-compatible implementation of WebSocket server, allowing real-time communication between the client and the server.
Similar to Action Cable, it routes messages based on "channels" and "streams" using just one underlying WebSocket connection and is fully compatible with @rails/actioncable.
See API docs for more information:
Rage Cable is always mounted as a separate Rack application, which gives you the freedom to use it either as part of your application or in standalone mode using a separate process.
To enable Rage Cable, update your config.ru
file to mount the RageCable
component at the URL of your choice:
map "/cable" do
run Rage.cable.application
end
You can also use middlewares that are specific to the WebSocket clients:
map "/cable" do
use MyWebSocketRateLimiter
run Rage.cable.application
end
The connection setup is similar to Action Cable - inherit from the Rage::Cable::Connection
class to accept or reject connections:
# app/channels/rage_cable/connection.rb
module RageCable
class Connection < Rage::Cable::Connection
identified_by :current_user
def connect
self.current_user = find_verified_user
end
private
def find_verified_user
if verified_user = User.find_by(id: cookies.encrypted[:user_id])
verified_user
else
reject_unauthorized_connection
end
end
end
end
Inside the connection class, you have access to the request
, cookies
, and session
objects. Also, query parameters can be accessed using the params
object.
A channel represents a specific type of messages coming through the underlying WebSocket connection. Rage::Cable::Channel
exposes the transmit
and broadcast
helpers along with the before_subscribe
/after_subscribe
hooks and the periodically
helper:
# app/channels/chat_channel.rb
class ChatChannel < Rage::Cable::Channel
def subscribed
stream_from "chat"
broadcast("chat", { message: "A new member has joined!" })
end
def unsubscribed
broadcast("chat", { message: "A member has left!" })
end
end
To migrate from ActionCable, mount the Rage.cable.application
in your config.ru
file and update parent classes for your connections and channels. Rage.cable.broadcast can be used to publish messages to streams.
The following benchmark shows the ability of both Rage and Rails to handle 10000 concurrent WebSocket connections.
Client application:
- Opens 10000 connections.
- Once a connection has been established, it subscribes to the
Chat
channel and starts sending messages at random intervals between 500ms and 2s. - Additionally, once all connections are established, the client starts sending a
broadcast
message every second. - The test is running for five minutes.
Server application:
- Running two workers on an EC2
m5.large
instance. - Once a connection is accepted, the application subscribes it to the
chat_Best Room
stream. - Once a regular message comes in, the server responds with the current timestamp.
- Once the
broadcast
message comes in, the server broadcasts the current timestamp to thechat_Best Room
stream.
class ChatChannel < Rage::Cable::Channel
def subscribed
stream_from "chat_#{params[:room]}"
end
def receive(data)
transmit({ i: (Time.now.to_f * 1000).to_i })
end
def broadcast_me
broadcast("chat_#{params[:room]}", { i: (Time.now.to_f * 1000).to_i })
end
end