ActionCable: WebSocket Connection

Time:2019-12-31

Every HTTP request is a process from request to response, so the HTTP server does not need to maintain any state,

While websocket requires the server to maintain all connection states, ruby is not very good at dealing with concurrency. Actioncable uses many interesting technologies for performance and ease of use.

For example, message’s Pub / sub uses redis’s Pub / sub (there are other adapters).

In the concurrent processing, the ThreadPoolExecutor of current ruby is used, while the connection of websocket is processed by nio4r and websocket driver.

The following mainly introduces these two technologies and I / O model.

websocket-driver

Websocket driver mainly deals with websocket protocol and I / O layer. That is to say, I / O events can be handled in different ways. At the same time, a series of events, such as: open,: message,: close, are provided for easy use.

The server side socket using websocket driver needs to implement two methods, URL andwrite(string)url

URL is the URL that users use to connect to websocket.

write(string)Method is used to write data into the stream.

After that, when I / O monitors and hears the data, callWebSocket::Driver#parseMethod to analyze the data.

After parsing, websocket will return the parsed data through the: message event.

The example given by websocket driver readme uses eventmachine to handle I / O operations, while actioncable uses nio4r directly.

I/O model

I / O operation is to copy data between main memory and peripheral devices.

Peripherals are generally much slower than main memory. In order to deal with speed mismatch, different methods can be used to operate I / O, I / O model.

Blocking IO

Synchronous blocking I / O is the traditional I / O model.

In short, when I / O is performed, the thread is suspended until I / O is completed, and then the operation after the program is executed. That is to say, during IO operation, the thread is always waiting, so it is called blocking io. Ruby provides io.read method.

Synchronous non blocking IO

During IO operation, whether the system is ready for data or not, it will return directly. If it is not ready, an error is returned. When the user receives the error, he can try the IO operation again. Ruby provides the io.read’nonblock method.

IO multiplexing

adoptselectLet kernal suspend the current thread and give control to the application when one or more I / O events occur.

IO multiplexing is suitable for scenarios where multiple IO objects need to be monitored at the same time.

The time complexity of select is O (n), and Linux provides a more efficient versionepoll, epoll time complexity is O (log n)). Thin provides the option to use epoll or not. Ruby provides the IO. Select method.

nio4r

Nio4r is a ruby implementation of Java. NiO, but it provides a simpler interface.

Nio4r has two main parts:

Selectors: used to monitor multiple I / O objects at the same time

Monitors: used to track I / O events of concern, such as reads.

require "nio"

server = TCPServer.new("127.0.0.1", 12345)

selector = NIO::Selector.new

3.times do
  client = server.accept
  _monitor = selector.register(client, :r)
end

ready = selector.select

First, create a NiO:: selector object, and then register the concerned I / O events to the selector object through NiO:: selector ා register.

Finally, in a loop, call the NiO:: selector ා select method to select the ready event.

The class handling I / O in actioncable is connection:: streameventloop, initializing selector in@nio ||= NIO::Selector.new, and then the streameventloop ා attach method registers the I / O event on the NiO selector.

Finally, the run method is used to process the event listening run, using theIO.read_nonblockRead the stream.

References

  • The underlying library supporting actioncable
  • Java NiO (3): IO model
  • Analysis of Java NiO
  • A gentle introduction to nio4r: low-level portable asynchronous I/O for Ruby
  • Computer Systems: A Programmer’s Perspective
  • Programming Erlang : Software for a Concurrent World

Recommended Today

Redis design and implementation 4: Dictionary Dict

In redis, the dictionary is the infrastructure. Redis database data, expiration time and hash type all take the dictionary as the underlying structure. Structure of dictionary Hashtable The implementation code of hash table is as follows:dict.h/dictht The dictionary of redis is implemented in the form of hash table. typedef struct dictht { //Hash table array, […]