You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -14,7 +15,7 @@ In essence, a super stream is a partitioned stream that brings scalability compa
14
15
The stream Java client uses the same programming model for super streams as with individual streams, that is the `Producer`, `Consumer`, `Message`, etc API are still valid when super streams are in use.
15
16
Application code should not be impacted whether it uses individual or super streams.
16
17
17
-
==== Topology
18
+
===== Topology
18
19
19
20
A super stream is made of several individual streams, so it can be considered a logical entity rather than an actual physical entity.
20
21
The topology of a super stream is based on the https://www.rabbitmq.com/tutorials/amqp-concepts.html[AMQP 0.9.1 model], that is exchange, queues, and bindings between them.
@@ -46,7 +47,7 @@ When a super stream is in use, the stream Java client queries this information t
46
47
From the application code point of view, using a super stream is mostly configuration-based.
47
48
Some logic must also be provided to extract routing information from messages.
48
49
49
-
==== Publishing to a Super Stream
50
+
===== Publishing to a Super Stream
50
51
51
52
When the topology of a super stream like the one described above has been set, creating a producer for it is straightforward:
Note using Java's `hashCode()` method is a debatable choice as potential producers in other languages are unlikely to implement it, making the routing different between producers in different languages.
79
80
80
-
==== Resolving Routes with Bindings
81
+
====== Resolving Routes with Bindings
81
82
82
83
Hashing the routing key to pick a partition is only one way to route messages to the appropriate streams.
83
84
The stream Java client provides another way to resolve streams, based on the routing key _and_ the bindings between the super stream exchange and the streams.
Internally the client will query the broker to resolve the destination streams for a given routing key, making the routing logic from any exchange type available to streams.
114
-
Note the client caches results, it does not query the broker for every message.
115
+
Note the client caches results, it does not query the broker for every message.
116
+
117
+
====== Using a Custom Routing Strategy
118
+
119
+
The solution that provides the most control over routing is using a custom routing strategy.
120
+
This should be needed only for specific cases.
121
+
122
+
The following code sample shows how to implement a simplistic round-robin `RoutingStrategy` and use it in the producer.
123
+
Note this implementation should not be used in production as the modulo operation is not sign-safe for simplicity's sake.
<2> Close the consumer when it is no longer necessary
150
+
151
+
A super stream consumer is a composite consumer: it will look up the super stream partitions and create a consumer for each or them.
152
+
153
+
====== Offset Tracking
154
+
155
+
The semantic of offset tracking for a super stream consumer are roughly the same as for an individual stream consumer.
156
+
There are still some subtle differences, so a good understanding of <<api.adoc#consumer-offset-tracking, offset tracking>> in general and of the <<api.adoc#consumer-automatic-offset-tracking,automatic>> and <<api.adoc#consumer-manual-offset-tracking,manual>> offset tracking strategies is recommended.
157
+
158
+
Here are the main differences for the automatic/manual offset tracking strategies between single and super stream consuming:
159
+
160
+
* *automatic offset tracking*: internally, _the client divides the `messageCountBeforeStorage` setting by the number of partitions for each individual consumer_.
161
+
Imagine a 3-partition super stream, `messageCountBeforeStorage` set to 10,000, and 10,000 messages coming in, perfectly balanced across the partitions (that is about 3,333 messages for each partition).
162
+
In this case, the automatic offset tracking strategy will not kick in, because the expected count message has not been reached on any partition.
163
+
Making the client divide `messageCountBeforeStorage` by the number of partitions can be considered "more accurate" if the message are well balanced across the partitions.
164
+
A good rule of thumb is to then multiply the expected per-stream `messageCountBeforeStorage` by the number of partitions, to avoid storing offsets too often. So the default being 10,000, it can be set to 30,000 for a 3-partition super stream.
165
+
* *manual offset tracking*: the `MessageHandler.Context#storeOffset()` method must be used, the `Consumer#store(long)` will fail, because an offset value has a meaning only in one stream, not in other streams.
166
+
A call to `MessageHandler.Context#storeOffset()` will store the current message offset in _its_ stream, but also the offset of the last dispatched message for the other streams of the super stream.
0 commit comments