One of the best thing about Rails is the ease with which it allows you to develop web apps quickly by providing some sensible conventions.
And with Rails 5, it allows you to make real-time web apps in a breeze
Introducing ActionCable.. a real time framework for communication over websockets.
But before we proceed any further, let’s spend some time discussing how we got to the action cable.. or particularly, the web sockets.
When the web started becoming more dynamic with ajax and js advances, we, as developers, started finding ways to make our applications more real-time.
One of the earliest solutions that came up was Polling.
The client send requests over HTTP at regular intervals… a simple and robust solution to implement !!
The interval plays a critical role here:
In order to give any real-time experience to the client, the polling interval needs to be small enough to make the user effectively believe that app is almost live with some network latency may be.
But there were problems :
If we try to make it more real-time by reducing polling interval, our servers didn’t like it mainly because of the way the polling.. or rather HTTP works.
Here’s a sample implementation from IBM
HTTP is a stateless protocol. The server and client are aware of each other only during the current request. Afterward, both of them forget about each other.
Which means… ?
For each request, there is additional data in the form of headers which gets transmitted through the network and therefore, the communication was inefficient.
As per this google’s whitepaper, typical headers size of 700-800 bytes is common.
Assuming 800 bytes,
For 1k clients polling every second, network throughput = 800 * 1000 = 0.763 MBps… For 10k clients… 7.63 MBps.
This was more like looping via setTimeout instead of doing it via setInterval.
The server receives the request and responds only when it has the response available.
Here’s a sample implementation from IBM
But again, that was not the solution either:
It quickly falls apart once the data begin to change frequently… that would be more like regular polling itself.
SERVER SENT EVENTS
Server-sent event support was added to Rails in 4.0, through ActionController::Live.
Here’s a nice intro from tenderlove
A persistent unidirectional connection is made between the server and the client. The client subscribes to the server events via onmessage callbacks.
Here’s a nice write-up on server sent events
That seemed promising for a while but the world stopped for IE users. As shown here, No version of IE implements EventSource interface which is required for server sent events. Whoosh! End of story.
Websockets work by maintaining a persistent bi-directional channel.
After the initial handshake, the HTTPÂ connection is upgraded to a WebSocket connection. The data frames can then pass to and fro between client and the server until one of the sides closes it.
More info here
Here’s a nice write up on websockets vs REST
…. Coming back to action cable..
Let’s get our head around some common terms that we would be using.
- Consumer – The client of a WebSocket connection is called the consumer.
- Channel – A channel encapsulates a logical unit of work, similar to what a controller does in a regular MVC setup.
- Subscriber – Each consumer can, in turn, subscribe (and therefore, will become a subscriber) to multiple cable channels.
As seen in the conceptual diagrams below from here
** This is just a bird-eye view. We will be covering the details as we proceed.
- An action cable server can run as a separate server or can be mounted on the Rails App server itself.
- The action cable server need not be a threaded server only. More info here (socket hijacking)
- A client (Browser) interacts with rails app over HTTP / HTTPS.
- The connection between client and ActionCable server is upgraded from HTTP to WS / WSS ( WebSocket Protocol ).
- The Rails App enqueues the publishing in an event queue ( default implementation uses Redis for this)
- The action cable server processes the queue.
You can follow below link to read the next part which is focussed on Implementing a sample Chat application using ActionCable.