Channels, Streams and Sessions
Before delving deeper into the files used by Aeron, we need to introduce some more terminology.
Channels
A Channel is a URI used to tell Aeron how to find the receiving side of a Publication.
A Channel is used to specify whether messages will be sent via IPC or UDP. If via UDP, the Channel also needs the host and port of the receiving side. A Channel is required when creating a Publication or a Subscription. For a Publication, it controls whether to create a Network or IPC Publication. There is only one kind of Subscription.
IPC Publications
For IPC Publications, the Channel URI has to start with aeron:ipc
. This can be used as is, or additional
parameters can be added, e.g. aeron:ipc?term-length=64k
. IPC URIs indicate messages will be written
to a local Publication log buffer file and don't need sending over the network, so the Sender and Receiver don't need
to be involved. On the receiving side, a Subscription created with an IPC URI will read directly from the Publication
log buffer, not an Image log buffer.
Network Publications
For Network Publications, the Channel URI has to start with aeron:udp
. The URI requires a parameter to specify an
endpoint on the Receiver, e.g. aeron:udp?endpoint=192.168.0.1:40456
. Other configuration parameters can be
added, e.g. aeron:udp?endpoint=192.168.0.1:40456|interface=192.168.0.3
.
Channels diagram
The above diagram is not complete (we'll build on it below), but it shows where Channels are used for Network Publications. Machine 3 has three channels for receiving messages. The Channels are numbered 1, 2 and 3 for conciseness, but real Channel URIs would include the IP address or hostname of Machine 3 and a port number.
On Machine 1, Publication 1 (the Client API object) and its log buffer are specific to Channel 2. The Sender will send messages over a UDP channel to the Channel 2 endpoint on Machine 3. When the Receiver on Machine 3 receives messages, it will put them into the Image log buffer. This will become a replica of the Publication log buffer, so it will also be specific to Channel 2. Finally, Subscription 1 (another Client API object) is also specific to Channel 2.
Link
For a detailed description of Channels, see the Aeron GitHub Channel Configuration page.
Streams
A StreamId is used to distinguish between different streams of messages, or conversations, that can flow over a Channel.
When creating a Publication or a Subscription, you actually need two parameters: a Channel and a StreamId. A StreamId is just an integer, and the application is free to allocate StreamIds however it likes. For a Network Publication, multiple Streams passing over a Channel means they share the same underlying UDP channel. This is good for performance, but is an internal detail within Aeron - there are no public, application level features that utilise the sharing of a Channel.
Channels and Streams diagram
We've expanded the earlier diagram and added Streams. Let's say the components in the earlier diagram used StreamId 4, and we add another Publication and Subscription that share Channel 2, but using StreamId 5. Now, the application on Machine 1 can send messages on Publication 1 to arrive on Subscription 1, and it can send messages on Publication 2 to arrive on Subscription 2. They share the same Channel, but the messages are kept separate.
When a message is written to a Publication log buffer, a frame header is added that contains the StreamId. When the Receiver receives a message, it knows which Channel it is for, because each underlying UDP channel is mapped to one Aeron Channel. The Receiver uses the StreamId in the frame header to identify which Image log buffer to write the message to.
Multiple writers
Aeron supports more than one Publication for the same Subscription. Imagine if a process on Machine 2 created a Publication on Channel 2 with StreamId 5. It would have its own Publication log buffer on Machine 2, which would be replicated to its own Image log buffer on Machine 3. Subscription 2 would read from both Image log buffers.
We just saw how the Receiver knows which Channel and StreamId a message is for. But if there are two Image log buffers for Channel 2 and StreamId 5, how does it know which Image log buffer to put incoming messages in? This is where SessionIds come in.
Sessions
SessionIds are used to distinguish between different Publications (multiple publishers) for a given Subscription.
When a Publication is created, the application has to provide the Channel and StreamId. Under the hood, Aeron generates a randomized SessionId (an integer) and makes the Publication specific to the Channel, StreamId and SessionId tuple. When a message is written to a Publication log buffer, the SessionId is written to the frame header alongside the StreamId. So, if there are two Publications for the same Channel and StreamId, they will have different SessionIds, which the Receiver can use to identify which Image log buffer a message needs writing to.
A Subscription is specific to a Channel and StreamId, but not SessionId. A Subscription will read from all Image log buffer files for its Channel and StreamId. They will be read in a round-robin fashion, which means message ordering across Sessions (across Image log buffers) is not guaranteed. Message ordering within a Session (within an Image log buffer) is guaranteed.
The SessionId is available to the application when reading messages from a Subscription.
Channels, Streams and Sessions Diagram
Here's the diagram for the scenario described above.
Publication 2 has a random SessionId of 34, which is added to its messages and replicated to its Image log buffer. Publication 3 has a different SessionId. You can see that everything is specific to a Channel, StreamId and SessionId tuple, except for Subscriptions, which are specific to just Channel and StreamId.
Slow Consumers
In the diagram above, if an application thread was reading from Stream 4 slowly (polling Subscription 1), this would not affect another application thread reading from Stream 5 (polling Subscription 2), even though the messages were sent over the same Channel.
Channels, Streams and Sessions for IPC Publications
When sending messages over IPC, there is no underlying UDP channel. Messages aren't actually sent anywhere. They are written to the Publication log buffer and are read directly by the Subscription.
The Channel is aeron:ipc
at a minimum. This does not identify a recipient, so for a Publication, it just means
don't send the message via UDP, i.e. don't do anything with it. For a Subscription, it means read the message
straight from the Publication log buffer, not an Image log buffer.
Streams still make sense for IPC comms. Different Streams can be used over IPC, i.e. there can be different Publication log buffers.
Sessions also make sense. It is possible to have multiple Publications for the same Subscription, even on the same machine. This involves using Exclusive Publications, which we'll explain in the next section.