RSocket versus Reactor-Netty

At first glance, RSocket does not seem very innovative; nowadays, we already have web servers such as RxNetty or Reactor-Netty (the default WebFlux wrapper for Netty). These solutions offer APIs (which allow reading or writing from/to the network) built on top of reactive streams types, implying backpressure support. However, the only issue with that kind of backpressure is that it works in isolation. Subsequently, this means that proper backpressure support is wired only between the component and the network.

For example, using Reactor-Netty, we can consume incoming bytes only when we are ready to do so. Similarly, the network's readiness is exposed as the Subscription#request method calls. The central problem here is that the actual demand of the components does not cross the network boundaries, as depicted in the following diagram:

Diagram 8.13. The example of backpressure in isolation

As we can see from the preceding diagram, there are two services here (Service A and  Service B). As well as that, we have an abstract Adapter here that allows service (business logic) to communicate with another service over the Network. In this example, suppose that our adapter is Reactor-Netty, which provides reactive access. This means that backpressure control is properly implemented at the transport level. Consequently, the adapter informs the publisher of approximately how many elements it can write at that moment. In our case, Service A creates a continuous connection (for instance, WebSocket connection) with Service B and, once the connection becomes available, it starts sending elements to the adapter. Consequently, the adapter takes proper care of writing elements to the network. On the opposite side of the connection, we have Service B, which consumes messages from the network over the same adapter. As a Subscriber, Service B expresses the demand to the adapter and, once the proper amount of bytes have been received, the adapter converts them into the logical element, sending this to the business logic. In the same way, once the element has been sent to the adapter, the adapter takes care of transforming it into bytes and then following the flow control defined at the transport level to send them to the network.

As we might remember from Chapter 3, Reactive Streams - the New Streams' Standard, the worst-case scenario in communication between a producer and consumer arises when the consumer is slow enough that the producer may easily overflow the consumer. To emphasize the problem of isolated backpressure, let's suppose that we have a slow consumer and a fast producer, so some part of the events are buffered in the Socket Buffer. Unfortunately, the size of the buffer is limited, and at some point, the network packets may start dropping. Of course, in many aspects, transport's behavior depends on the interaction protocol. For example, reliable network transports such as TCP have a flow control (backpressure control) that embraces the notion of the sliding window and acknowledgement. This means that, in general, backpressure is achievable on a binary level (on the level of the received bytes and the corresponding acknowledgment). In such a case, TCP takes care of redelivering the messages and cases in which the lack of acknowledgments slows down the publisher on the side of Service A. The drawback here is that the impact on the performance of the applications itself is high since we have to take care of the redelivery of dropped packages. Moreover, the performance of the communication may also be decreased, so the overall stability of the system may be lost. Although such a transport flow control may be acceptable, the utilization of the connection is low. This is because we can't reuse the same connection for multiplexing several logical streams. Another aspect is when the consumer can't follow the transport flow control so the consumer continues buffering bytes internally which may end up with OutOfMemoryError.

To learn more about TCP flow control, please see the following link:
https://hpbn.co/building-blocks-of-tcp/#flow-control

In contrast to the isolated reactive Publisher-Subscriber communication, which may be easily achieved using Reactor Netty or RxNetty, RSockets offers a binary protocol that is an application protocol for reactive streams semantics across an asynchronous, network boundary:

Diagram 8.14. An example of backpressure with RSocket

As we can see from the preceding diagram, with the RSocket protocol, we get support for transmitting demand over network boundaries. Hence, the producer service may react to the request and send the corresponding number of onNext signals that are transmitted through the network as well. Besides, RSocket works on top of the adapter that takes care of the data writing to the network so that the local demand may be coordinated in isolation with the received demand from the consumer service. In general, RSocket is a transport agnostic that, along with TCP, supports Aeron and communication over WebSocket.

At first glance, it seems that the connection's usage is inefficient since the interaction between services may be low. However, one of the powerful features of the RSocket protocol is that it allows reusing the same socket connection for many streams between the same server and client. Hence, it may optimize the use of one connection.

Along with the protocol, RSockets enables symmetric interaction models such as the following:

  • Request/response: A stream of one element in the request and response
  • Request/stream: A stream of one element in the request stream and a finite/infinite stream as the response
  • Fire-and-forget: A stream of one element in the request and a Void (no elements) response stream
  • Channel: Fully bi-directional finite/infinite streams for both the request and response

As we can see, RSocket provides a wide list of commonly used interaction models for async message passing, acquiring only a single connection at the very beginning.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.97.40