Ring-Coordinator
Overview
As mentioned in the previous section, the retry ring-coordinator is a separate service — distinct from your utility microservices — that runs as either a master or a slave, depending on how it is configured.
This section walks through how the retry ring-coordinator is set up and how it works.
The Master and Slave retry ring-coordinator instances can also be deployed within the same service instance.
Refer to the deployment topologies section for more details.
|
After adding the stacksaga-ring-coordinator-spring-boot-starter dependency to your project and configuring the retry ring-coordinator as master or slave, you can run the retry ring-coordinator as a Spring Boot application.
|
How Master and Slave Connect
Before configuring each role, it helps to see how a Master and a Slave find each other.
On startup, a Slave opens a persistent RSocket connection to the Master using the host and port configured via stacksaga.coordinator.slave.target-master.*.
The Master accepts the connection and adds the Slave to its registry — from its next 30-second publish cycle onward, the Master starts sending that Slave its token-range updates.
The Retry-Coordinator-Slave section of the architecture guide covers what happens next — how the Slave divides its range across Orchestrator instances.
Ring-Coordinator As Master
If the retry ring-coordinator is configured as master, it is responsible for managing the entire token ring and sharing partitions of it with every slave retry ring-coordinator connected to it within the same region and cluster.
Read more about the Master’s responsibilities here.
Add the stacksaga-ring-coordinator-spring-boot-starter dependency to your project as follows:
<dependencyManagement>
<dependencies>
<dependency> <!--Only for stacksaga dependencies version management-->
<groupId>org.stacksaga</groupId>
<artifactId>stacksaga-bom</artifactId>
<version1.0.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.stacksaga</groupId>
<artifactId>stacksaga-ring-coordinator-spring-boot-starter</artifactId>
</dependency>
</dependencies>
|
To run the retry ring-coordinator as a Spring application, you do not need any web-related dependencies such as In production, however, you will usually want visibility into its metrics and other monitoring data.
Add the |
Configuration
The retry ring-coordinator can be configured via application.properties or application.yml.
Below is a minimal configuration for the retry ring-coordinator as master:
#stacksaga-master coordinator configuration
stacksaga.coordinator.instance-type=master (1)
stacksaga.coordinator.target-services=order-service (2)
#stacksaga-instance configuration
stacksaga.instance.cluster=cluster1 (3)
stacksaga.instance.region=us-east-1 (4)
stacksaga.instance.zone=us-east-1a (5)
#rsocket server configuration
spring.rsocket.server.port=1000 (6)
spring.rsocket.server.address=localhost (7)
spring.rsocket.server.transport=tcp (8)
| 1 | Set stacksaga.coordinator.instance-type to master, since this instance runs as the Master. |
| 2 | The target service(s) this Master coordinates retries for — order-service in this example.
This can be a comma-separated list when a single Master manages multiple services; see the deployment topologies section. |
| 3 | The cluster this instance belongs to.
Only slave retry ring-coordinator instances and Orchestrators in the same cluster can connect to this Master — see the Virtual Cluster section. |
| 4 | The region this instance belongs to.
Only slave retry ring-coordinator instances and Orchestrators in the same region can connect to this Master — see the Regional Deployment section. |
| 5 | The zone this instance belongs to.
It has no functional impact here, but should be set as per the StackSaga core specification. |
| 6 | The RSocket server port. slave retry ring-coordinator instances connect to the Master over RSocket — backed by the default RSocket server provided by spring-boot-starter-rsocket — and Orchestrators use the same port to look up which slave instance to connect to. |
| 7 | The RSocket network address that the server binds to. |
| 8 | The RSocket transport protocol.
It must be tcp for retry ring-coordinator services. |
Ring-Coordinator As Slave
If the retry ring-coordinator is configured as slave, it is responsible for connecting to the master retry ring-coordinator, subscribing to receive its assigned ring portion, and publishing sub-ring portions to the Orchestrator instances subscribed to it within the same region and cluster.
Read more about the Slave’s responsibilities here.
Adding the stacksaga-ring-coordinator-spring-boot-starter dependency is exactly the same as for the Master — both roles use the same starter.
Only the configuration differs, as shown below.
Configuration
#stacksaga-slave coordinator configuration
stacksaga.coordinator.instance-type=slave (1)
stacksaga.coordinator.target-services=order-service (2)
#stacksaga-instance configuration
stacksaga.instance.cluster=cluster1 (3)
stacksaga.instance.region=us-east-1 (4)
stacksaga.instance.zone=us-east-1a (5)
#rsocket server configuration
spring.rsocket.server.port=1001 (6)
spring.rsocket.server.address=localhost (7)
spring.rsocket.server.transport=tcp (8)
#connecting to the master retry ring-coordinator
stacksaga.coordinator.slave.target-master.port=1000 (9)
stacksaga.coordinator.slave.target-master.host=localhost (10)
| 1 | Set stacksaga.coordinator.instance-type to slave, since this instance runs as a Slave. |
||
| 2 | The target service(s) this Slave subscribes to on the Master, receiving their ring portion and publishing sub-ring portions to the subscribed Orchestrator instances.
This can be a comma-separated list when a single Slave subscribes for multiple services; see the deployment topologies section.
|
||
| 3 | The cluster this instance belongs to — same semantics as for the Master.
The Master, and any Orchestrator instances that want to subscribe to this Slave, must share this cluster name for the connection to succeed. |
||
| 4 | The region this instance belongs to — same semantics as for the Master.
The Master, and any subscribing Orchestrator instances, must share this region for the connection to succeed. |
||
| 5 | The zone this instance belongs to.
It has no functional impact here, but should be set as per the StackSaga core specification. |
||
| 6 | The RSocket server port.
Orchestrator instances connect to this Slave over RSocket to receive their sub-range updates. |
||
| 7 | The RSocket network address that the server binds to. |
||
| 8 | The RSocket transport protocol.
It must be tcp for retry ring-coordinator services. |
||
| 9 | The RSocket server port of the Master this Slave connects to, in the same region and cluster. |
||
| 10 | The RSocket server host of the Master this Slave connects to, in the same region and cluster. |
Configuration Properties Reference
The following table summarizes all the configuration properties for the retry ring-coordinator. The first group applies to both master and slave instances; the second group applies only to slave instances.
Properties shown with a dash (-) in the Default column are mandatory and have no default — you must set them explicitly.
|
| Property Name | Default | Type | Description |
|---|---|---|---|
Common — applies to both Master and Slave instances |
|||
|
- |
|
The role this instance runs as — |
|
- |
|
A comma-separated list of the service(s) this instance handles. The Master uses it to decide which Slaves may connect to it; a Slave uses it to decide which Master to connect to. Every service supported by a Slave must also be supported by its Master, otherwise the connection is rejected — but a Master may support more services than any single Slave. |
|
- |
|
The port the embedded RSocket server binds to. Slaves connect to the Master on this port, and Orchestrators connect to a Slave on this port, so it serves both connection types. |
|
- |
|
The network address the embedded RSocket server binds to. |
|
- |
|
The transport protocol for the embedded RSocket server. Must be |
|
- |
|
The cluster this instance belongs to. Components only connect to one another when their |
|
- |
|
The region this instance belongs to. Components only connect to one another when their |
|
- |
|
The zone this instance belongs to. It has no functional impact here, but should be set as per the StackSaga core specification. |
Slave-only — applies to |
|||
|
- |
|
The host of the Master this Slave connects to (in the same region and cluster). Used to establish the RSocket connection from the Slave to the Master. |
|
- |
|
The port of the Master this Slave connects to (in the same region and cluster). Used to establish the RSocket connection from the Slave to the Master. |
|
|
|
Maximum number of TCP reconnect attempts when establishing the connection to the Master. If the Slave still cannot connect after this many attempts, the instance shuts down. |
|
|
|
The initial backoff between TCP reconnect attempts. After a failed attempt the Slave waits this long before retrying, growing on each subsequent attempt up to |
|
|
|
The upper bound on the TCP reconnect backoff. The growing backoff between reconnect attempts never exceeds this value. |
|
|
|
Maximum number of RSocket stream retry attempts before giving up. This governs recovery of the RSocket stream itself, and is distinct from the TCP |
|
|
|
The initial backoff between RSocket stream retry attempts. After a failed attempt the Slave waits this long before retrying, growing on each subsequent attempt up to |
|
|
|
The upper bound on the RSocket stream retry backoff. The growing backoff between retry attempts never exceeds this value. |
|
|
|
The jitter factor applied to the RSocket stream retry backoff. Randomizing the backoff avoids a thundering-herd problem when many Slaves reconnect to the Master at once. Must be between |
|
|
|
Controls what the Master hands back to Orchestrators when they look up the available Slaves to connect to. When |