Skip to content

Cluster Client

This page covers the client side of a cluster connection. Later pages will discuss how client sessions are handled in the Consensus Module and Clustered Service.

Clients interact with the Cluster through the AeronCluster Client API class. It can be used to connect / disconnect from the Cluster, send Ingress messages, poll for Egress messages, and request a snapshot (which can also be done independently using ClusterTool).

It is aware of all Cluster members and can connect to any of them, but if connects to a follower, it will be redirected to the leader. Once it finds the leader, will stay connected to it. If there is an Election, the new leader will notify it, and it will automatically switch its connection to it. However, if it loses the connection for whatever reason, it will not reconnect - this needs to be done in application code.

Client Configuration

The AeronCluster class contains Configuration and Context inner classes for configuring it. This pattern is also used in the Consensus Module and Clustered Service.

  • the Configuration inner class contains static methods for reading System properties for configuring the client, along with default values
  • the Context inner class is a programmable configuration object that is passed into AeronCluster. You create an instance of the Context, which defaults a lot of its values from the Configuration class. You can then programmatically override values on the Context object before passing it into AeronCluster

The important parts of the Context that a Client Application needs to set are (see code snippet in Cluster Tutorial example):

  • a reference to an object that implements the EgressListener interface, for handling Egress messages from the Cluster
  • the Egress Channel (e.g. aeron:udp?endpoint=<client host>:0) of the client, which will be sent to the Cluster so it can connect back to the client. If the port number is zero, the client will use an ephemeral port and send that to the cluster
  • the Ingress Channel, which could just be aeron:udp, or could be a multicast address to reach the cluster members
  • the Ingress endpoints from the cluster member endpoints, so the client can connect to each cluster member (unless using multicast). This looks like 0=<host>:<port>,1=<host>:<port>,2=<host>:<port>, where the hosts are the cluster members and ports are the Ingress ports

AeronCluster.connect()

The static AeronCluster.connect(Context) method is used to connect to the Cluster and create an AeronCluster client object.

Client Application Client Code EgressListener concludes creates AsyncConnect poll creates Context (concluded) connect(Context) Transport Client Client Conductor Egress Subscription Ingress Publication Egress Ingress AeronCluster (Client) Context (concluded) creates Media Driver Sender Receiver Driver Conductor

Use the tabs above to step through the animation.



The Client Application calls AeronCluster.connect(Context), which starts by 'concluding' the AeronCluster.Context. The main job of conclude is to create the Aeron Transport client, which connects to the Media Driver.

The connect() method creates an AsyncConnect object, passing it the concluded Context. AsyncConnect is what connects to the Cluster, before creating the AeronCluster client object. It is async because the caller (the connect() method) has to keep polling it to progress the connection, and can perform other work in between each poll. If the transport client was configured to use an AgentInvoker instead of having its own thread for the Client Conductor, connect() would have to invoke it after each poll.

AsyncConnect creates the Egress Subscription, then creates Ingress Publications to the Cluster members and sends a SessionConnectRequest to the first one that connects. If it connects to a follower, it is redirected to the leader. On success, the leader returns a SessionEvent, with an EventCode of OK. AsyncConnect is described more below. When It has finished, there will be an Ingress connection to the leader, and the leader will have an Egress connection back to the client.

AsyncConnect finishes by creating an AeronCluster Client object, passing it the Context, Ingress Publication and Egress Subscription. It also passes it values returned by the leader: the connection's clusterSessionId (which needs to be passed in all subsequent Ingress messages), current leadershipTermId, and leaderMemberId. Any Ingress Publications to followers are closed at this point.

The connect() method returns the AeronCluster object to the Client application. The Client application can use it to publish messages on the Ingress, and poll the Egress, which will deliver messages to the EgressListener.


Authentication

Aeron Cluster supports authenticating Client connections, but it is disabled by default. Configuring authentication requires a CredentialsSupplier in the Client and an Authenticator in the Consensus Module (the Consensus Module side is discussed later in Authentication).

There are two levels of authentication. The first is authentication of the encoded credentials in the SessionConnectRequest. AsyncConnect automatically sets these from the CredentialsSupplier, which is a configuration setting on the Context. The default supplier returns empty credentials. When the Consensus Module receives the SessionConnectRequest, it authenticates the credentials, and accepts or rejects the connection. The default no-op Authenticator in the Consensus Module simply marks the connection as authenticated, without checking the credentials.

The second level of authentication is a challenge-response exchange. The Authenticator in the Consensus Module can reply to the SessionConnectRequest with a Challenge message on the Egress. In the Client, AsyncConnect automatically replies with a ChallengeResponse that contains an encoded response to the Challenge, which also comes from the CredentialsSupplier.

AsyncConnect

AsyncConnect has a small state machine that handles the connection sequence. AsyncConnect uses an EgressPoller, which is a helper object for parsing and capturing the contents of Egress messages (it isn't used anywhere else). The state machine progresses in sequence from top to bottom, unless authentication challenged, or it is redirected from a follower to the leader.

  • CREATE_EGRESS_SUBSCRIPTION - creates the Egress Subscription and once created, wraps it with an EgressPoller
  • CREATE_INGRESS_PUBLICATIONS - creates an Ingress Publication to each cluster member if unicast, or one Ingress Publication if it is multicast. By default, Ingress Publications are ExclusivePublications, but can be configured to be ConcurrentPublications so they can be used by multiple threads
  • AWAIT_PUBLICATION_CONNECTED - if the Ingress is unicast, it waits for the first Ingress Publication to be connected. If it's multicast, it waits for the multicast Publication to be connected. Once connected, it resolves the Egress endpoint (resolving the actual port, if it is ephemeral) and prepares the SessionConnectRequest, including credentials from the CredentialsSupplier
  • SEND_MESSAGE - sends the prepared message to the cluster on the Ingress Publication
  • POLL_RESPONSE - polls the EgressPoller for one message
    • if it receives a Challenge, it prepares a ChallengeResponse, getting the response data from the CredentialsSupplier, and moves back to the SEND_MESSAGE state
    • if it receives a SessionEvent, then it checks the EventCode
      • if it's OK, it moves to CONCLUDE_CONNECT
      • if it's AUTHENTICATION_REJECTED or ERROR, it throws an exception
      • if it's REDIRECT, it reads the leaderMemberId and updates all the Ingress endpoints from the message. Then it disconnects any Ingress Publications, creates an Ingress Publication to the leader, and moves back to AWAIT_PUBLICATION_CONNECTED
  • CONCLUDE_CONNECT - it is now connected to the leader's Ingress and the leader has connected back to the client on the client's Egress. It creates an AeronCluster object that contains the Ingress Publication and Egress Subscription, the clusterSessionId assigned to this session by the leader, the leadershipTermId and leaderMemberId. Finally, it closes any Ingress Publications to the followers and returns the AeronCluster object

AeronCluster API

Once a client has connected to the Cluster, the AeronCluster object lets it:

  • send messages to the cluster using tryClaim() / offer() methods
  • poll the Egress - this needs to be done regularly to pick up Egress messages, and to detect leadership changes
  • send keepalive messages to the cluster if not sending Ingress messages regularly. This prevents the cluster from timing out the connection
  • request the cluster to take a snapshot
  • close the connection