A RabbitMQ stream is a persistent and replicated data structure that models an append-only log. It differs from the classical RabbitMQ queue in the way message consumption works. In a classical RabbitMQ queue, consuming removes messages from the queue. In a RabbitMQ stream, consuming leaves the stream intact. So the content of a stream can be read and re-read without impact or destructive effect.
None of the stream or classical queue data structure is better than the other, they are usually suited for different use cases.
RabbitMQ Stream was developed to cover the following messaging use cases:
-
Large fan-outs: when several consumer applications need to read the same messages.
-
Replay / Time-traveling: when consumer applications need to read the whole history of data or from a given point in a stream.
-
Throughput performance: when higher throughput than with other protocols (AMQP, STOMP, MQTT) is required.
-
Large logs: when large amount of data need to be stored, with minimal in-memory overhead.
It is also possible to use the stream abstraction in RabbitMQ with the AMQP 0-9-1 protocol. Instead of consuming from a stream with the stream protocol, one consumes from a "stream-powered" queue with the AMQP 0-9-1 protocol. A "stream-powered" queue is a special type of queue that is backed up with a stream infrastructure layer and adapted to provide the stream semantics (mainly non-destructive reading).
Using such a queue has the advantage to provide the features inherent to the stream abstraction (append-only structure, non-destructive reading) with any AMQP 0-9-1 client library. This is clearly interesting when considering the maturity of AMQP 0-9-1 client libraries and the ecosystem around AMQP 0-9-1.
But by using it, one does not benefit from the performance of the stream protocol, which has been designed for performance in mind, whereas AMQP 0-9-1 is a more general-purpose protocol.
It is not possible to use "stream-powered" queues with the stream Java client, you need to use an AMQP 0-9-1 client library.
RabbitMQ stream provides at-least-once guarantees thanks to the publisher confirm mechanism, which is supported by the stream Java client.
Message deduplication is also supported on the publisher side.
The RabbitMQ Stream Java Client implements the RabbitMQ Stream protocol and avoids dealing with low-level concerns by providing high-level functionalities to build fast, efficient, and robust client applications.
-
administrate streams (creation/deletion) directly from applications. This can also be useful for development and testing.
-
adapt publishing throughput thanks to the configurable batch size and flow control.
-
avoid publishing duplicate messages thanks to message deduplication.
-
consume asynchronously from streams and resume where left off thanks to automatic or manual offset tracking.
-
enforce best practices to create client connections – to stream leaders for publishers to minimize inter-node traffic and to stream replicas for consumers to offload leaders.
-
optimize resources thanks to automatic growing and shrinking of connections depending on the number of publishers and consumers.
-
let the client handle network failure thanks to automatic connection recovery and automatic re-subscription for consumers.
-
publish metrics to monitoring systems like Prometheus and ship spans to distributed tracing backends like OpenZipkin or Wavefront thanks to built-in support for Micrometer.
The RabbitMQ Stream Java Client is in development and stabilization phase. When the stabilization phase ends, a 1.0.0 version will be cut, and semantic versioning is likely to be enforced.
Before reaching the stable phase, the client will use a versioning scheme of [0.MINOR.PATCH]
where:
-
0
indicates the project is still in a stabilization phase. -
MINOR
is a 0-based number incrementing with each new release cycle. It generally reflects significant changes like new features and potentially some programming interfaces changes. -
PATCH
is a 0-based number incrementing with each service release, that is bux fixes.
Breaking changes between releases can happen but will be kept to a minimum. The next section provides more details about the evolution of programming interfaces.
The RabbitMQ Stream Java Client is in active development but its programming interfaces will remain as stable as possible. There is no guarantee though that they will remain completely stable, at least until it reaches version 1.0.0.
The client contains 2 sets of programming interfaces whose stability are of interest for application developers:
-
Application Programming Interfaces (API): those are the ones used to write application logic. They include the interfaces and classes in the
com.rabbitmq.stream
package (e.g.Producer
,Consumer
,Message
). These API constitute the main programming model of the client and will be kept as stable as possible. -
Service Provider Interfaces (SPI): those are interfaces to implement mainly technical behavior in the client. They are not meant to be used to implement application logic. Application developers may have to refer to them in the configuration phase and if they want to customize some internal behavior of the client. SPI include interfaces and classes in the
com.rabbitmq.stream.codec
,com.rabbitmq.stream.compression
,com.rabbitmq.stream.metrics
packages, among others. These SPI are susceptible to change, but this should have no impact on most applications, as the changes are likely to be limited to the client internals.