Overview
RSocket is an application protocol for multiplexed, duplex communication over TCP, WebSocket, and other byte stream transports, using one of the following interaction models:
-
Request-Response
— send one message and receive one back. -
Request-Stream
— send one message and receive a stream of messages back. -
Channel
— send streams of messages in both directions. -
Fire-and-Forget
— send a one-way message.
Once the initial connection is made, the "client" vs "server" distinction is lost as both sides become symmetrical and each side can initiate one of the above interactions. This is why in the protocol calls the participating sides "requester" and "responder" while the above interactions are called "request streams" or simply "requests".
These are the key features and benefits of the RSocket protocol:
-
Reactive Streams semantics across network boundary — for streaming requests such as
Request-Stream
andChannel
, back pressure signals travel between requester and responder, allowing a requester to slow down a responder at the source, hence reducing reliance on network layer congestion control, and the need for buffering at the network level or at any level. -
Request throttling — this feature is named "Leasing" after the
LEASE
frame that can be sent from each end to limit the total number of requests allowed by other end for a given time. Leases are renewed periodically. -
Session resumption — this is designed for loss of connectivity and requires some state to be maintained. The state management is transparent for applications, and works well in combination with back pressure which can stop a producer when possible and reduce the amount of state required.
-
Fragmentation and re-assembly of large messages.
-
Keepalive (heartbeats).
RSocket has implementations in multiple languages. The Java library is built on Project Reactor, and Reactor Netty for the transport. That means signals from Reactive Streams Publishers in your application propagate transparently through RSocket across the network.
The Protocol
One of the benefits of RSocket is that it has well defined behavior on the wire and an easy to read specification along with some protocol extensions. Therefore it is a good idea to read the spec, independent of language implementations and higher level framework APIs. This section provides a succinct overview to establish some context.
Connecting
Initially a client connects to a server via some low level streaming transport such
as TCP or WebSocket and sends a SETUP
frame to the server to set parameters for the
connection.
The server may reject the SETUP
frame, but generally after it is sent (for the client)
and received (for the server), both sides can begin to make requests, unless SETUP
indicates use of leasing semantics to limit the number of requests, in which case
both sides must wait for a LEASE
frame from the other end to permit making requests.
Making Requests
Once a connection is established, both sides may initiate a request through one of the
frames REQUEST_RESPONSE
, REQUEST_STREAM
, REQUEST_CHANNEL
, or REQUEST_FNF
. Each of
those frames carries one message from the requester to the responder.
The responder may then return PAYLOAD
frames with response messages, and in the case
of REQUEST_CHANNEL
the requester may also send PAYLOAD
frames with more request
messages.
When a request involves a stream of messages such as Request-Stream
and Channel
,
the responder must respect demand signals from the requester. Demand is expressed as a
number of messages. Initial demand is specified in REQUEST_STREAM
and
REQUEST_CHANNEL
frames. Subsequent demand is signaled via REQUEST_N
frames.
Each side may also send metadata notifications, via the METADATA_PUSH
frame, that do not
pertain to any individual request but rather to the connection as a whole.
Message Format
RSocket messages contain data and metadata. Metadata can be used to send a route, a
security token, etc. Data and metadata can be formatted differently. Mime types for each
are declared in the SETUP
frame and apply to all requests on a given connection.
While all messages can have metadata, typically metadata such as a route are per-request
and therefore only included in the first message on a request, i.e. with one of the frames
REQUEST_RESPONSE
, REQUEST_STREAM
, REQUEST_CHANNEL
, or REQUEST_FNF
.
Protocol extensions define common metadata formats for use in applications:
-
Composite Metadata-- multiple, independently formatted metadata entries.
-
Routing — the route for a request.
Java Implementation
The Java implementation for RSocket is built on
Project Reactor. The transports for TCP and WebSocket are
built on Reactor Netty. As a Reactive Streams
library, Reactor simplifies the job of implementing the protocol. For applications it is
a natural fit to use Flux
and Mono
with declarative operators and transparent back
pressure support.
The API in RSocket Java is intentionally minimal and basic. It focuses on protocol features and leaves the application programming model (e.g. RPC codegen vs other) as a higher level, independent concern.
The main contract
io.rsocket.RSocket
models the four request interaction types with Mono
representing a promise for a
single message, Flux
a stream of messages, and io.rsocket.Payload
the actual
message with access to data and metadata as byte buffers. The RSocket
contract is used
symmetrically. For requesting, the application is given an RSocket
to perform
requests with. For responding, the application implements RSocket
to handle requests.
This is not meant to be a thorough introduction. For the most part, Spring applications will not have to use its API directly. However it may be important to see or experiment with RSocket independent of Spring. The RSocket Java repository contains a number of sample apps that demonstrate its API and protocol features.
Spring Support
The spring-messaging
module contains the following:
-
rsocket-requester — fluent API to make requests through an
io.rsocket.RSocket
with data and metadata encoding/decoding. -
rsocket-annot-responders —
@MessageMapping
annotated handler methods for responding.
The spring-web
module contains Encoder
and Decoder
implementations such as Jackson
CBOR/JSON, and Protobuf that RSocket applications will likely need. It also contains the
PathPatternParser
that can be plugged in for efficient route matching.
Spring Boot 2.2 supports standing up an RSocket server over TCP or WebSocket, including
the option to expose RSocket over WebSocket in a WebFlux server. There is also client
support and auto-configuration for an RSocketRequester.Builder
and RSocketStrategies
.
See the
RSocket section
in the Spring Boot reference for more details.
Spring Security 5.2 provides RSocket support.
Spring Integration 5.2 provides inbound and outbound gateways to interact with RSocket clients and servers. See the Spring Integration Reference Manual for more details.
Spring Cloud Gateway supports RSocket connections.