重试环协调器 (Ring-Coordinator)
概述 (Overview)
正如 上一章节 中所述,重试环协调器 (Retry Ring-Coordinator) 是一个独立于业务微服务的专门服务。根据配置,它以 master (主) 或 slave (从) 角色运行。
本章节将详细介绍重试环协调器的搭建步骤与运行机制。
Master 和 Slave 重试环协调器实例也可以部署在同一个服务实例中。
详情请参阅 部署拓扑 (Deployment Topologies) 章节。
|
在项目中添加 stacksaga-ring-coordinator-spring-boot-starter 依赖并将重试环协调器配置为 master 或 slave 之后,即可将其作为标准的 Spring Boot 应用程序运行。
|
Master 与 Slave 如何建立连接
在深入配置各角色之前,先了解 Master 与 Slave 之间如何互相发现与建连。
在启动时,Slave 会根据 stacksaga.coordinator.slave.target-master.* 配置的主机名和端口,向 Master 发起持久的 RSocket 连接。
Master 接受该连接并将该 Slave 添加到其实时注册表中——从接下来的 30 秒发布周期开始,Master 会定期向该 Slave 发送其分配的令牌范围更新 (Token-Range Updates)。
架构指南中的 Retry-Coordinator-Slave 章节 详细介绍了后续工作流程——即 Slave 如何将其令牌范围进一步切分并下发给各个 Orchestrator 实例。
以 Master 角色运行 Ring-Coordinator
如果将重试环协调器配置为 master,它负责管理整个令牌环 (Token Ring),并将令牌环的分区分配给同一区域 (Region) 和集群 (Cluster) 内连接到它的每个 slave 重试环协调器。
阅读更多关于 Master 职责的说明请参阅 此处。
在项目中添加 stacksaga-ring-coordinator-spring-boot-starter 依赖,如下所示:
<dependencyManagement>
<dependencies>
<dependency> <!--仅用于 stacksaga 依赖项版本管理-->
<groupId>org.stacksaga</groupId>
<artifactId>stacksaga-bom</artifactId>
<version>1.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>
|
要将重试环协调器作为 Spring 应用程序运行,您*不需要*引入任何 Web 相关依赖(如 但在生产环境中,通常需要监控其指标(Metrics)和其他健康数据。您可以添加 |
配置 (Configuration)
重试环协调器可以通过 application.properties 或 application.yml 进行配置。
以下是作为 master 运行的重试环协调器的最小配置示例:
#stacksaga-master 协调器配置
stacksaga.coordinator.instance-type=master (1)
stacksaga.coordinator.target-services=order-service (2)
#stacksaga-instance 元数据配置
stacksaga.instance.cluster=cluster1 (3)
stacksaga.instance.region=us-east-1 (4)
stacksaga.instance.zone=us-east-1a (5)
#rsocket 服务端配置
spring.rsocket.server.port=1000 (6)
spring.rsocket.server.address=localhost (7)
spring.rsocket.server.transport=tcp (8)
| 1 | 将 stacksaga.coordinator.instance-type 设置为 master,声明该实例作为 Master 运行。 |
| 2 | 该 Master 协调重试的目标服务名称——本例中为 order-service。当单个 Master 同时管理多个微服务时,可以使用逗号分隔的服务列表;详见 部署拓扑 章节。 |
| 3 | 该实例所属的集群标识 (cluster)。只有位于同一集群内的 slave 重试环协调器实例和 Orchestrator 才能连接到该 Master——详见 虚拟集群 (Virtual Cluster) 章节。 |
| 4 | 该实例所属的区域标识 (region)。只有位于同一区域内的 slave 重试环协调器实例和 Orchestrator 才能连接到该 Master——详见 区域化部署 (Regional Deployment) 章节。 |
| 5 | 该实例所属的可用区标识 (zone)。在此处对重试没有功能性影响,但应按照 StackSaga 核心规范进行配置。 |
| 6 | RSocket 服务端端口。slave 重试环协调器实例通过 RSocket 连接到 Master(底层由 spring-boot-starter-rsocket 提供的默认 RSocket 服务器支撑),Orchestrator 也使用该端口查找应连接哪一个 slave 实例。 |
| 7 | RSocket 服务端绑定的网络地址。 |
| 8 | RSocket 传输层协议。对于重试环协调器服务,必须为 tcp。 |
以 Slave 角色运行 Ring-Coordinator
如果将重试环协调器配置为 slave,它负责连接到 master 重试环协调器,订阅并接收分配给它的令牌环分区,并将细分的子令牌环分区发布给同一区域和集群内订阅它的各个 Orchestrator 实例。
阅读更多关于 Slave 职责的说明请参阅 此处。
添加 stacksaga-ring-coordinator-spring-boot-starter 依赖的方式与 Master 完全相同——两个角色共享同一个 Starter 依赖。
唯一的区别在于配置参数,如下所示:
配置 (Configuration)
#stacksaga-slave 协调器配置
stacksaga.coordinator.instance-type=slave (1)
stacksaga.coordinator.target-services=order-service (2)
#stacksaga-instance 元数据配置
stacksaga.instance.cluster=cluster1 (3)
stacksaga.instance.region=us-east-1 (4)
stacksaga.instance.zone=us-east-1a (5)
#rsocket 服务端配置
spring.rsocket.server.port=1001 (6)
spring.rsocket.server.address=localhost (7)
spring.rsocket.server.transport=tcp (8)
#连接目标 Master 重试环协调器
stacksaga.coordinator.slave.target-master.port=1000 (9)
stacksaga.coordinator.slave.target-master.host=localhost (10)
| 1 | 将 stacksaga.coordinator.instance-type 设置为 slave,声明该实例作为 Slave 运行。 |
||
| 2 | 该 Slave 向 Master 订阅的目标服务名称,接收对应服务的环分区并将子分区发布给订阅的 Orchestrator 实例。当单个 Slave 订阅多个服务时,可以使用逗号分隔列表;详见 部署拓扑 章节。
|
||
| 3 | 该实例所属的集群标识 (cluster)——语义与 Master 一致。Master 以及所有希望订阅该 Slave 的 Orchestrator 实例必须具有相同的集群名称,连接才能成功建立。 |
||
| 4 | 该实例所属的区域标识 (region)——语义与 Master 一致。Master 与所有订阅它的 Orchestrator 必须位于同一区域。 |
||
| 5 | 该实例所属的可用区标识 (zone)。在此处对重试没有功能性影响,但应按照规范配置。 |
||
| 6 | RSocket 服务端端口。Orchestrator 实例通过此端口连接到该 Slave 以接收其细分令牌范围更新。 |
||
| 7 | RSocket 服务端绑定的网络地址。 | ||
| 8 | RSocket 传输层协议,对于重试环协调器服务必须为 tcp。 |
||
| 9 | 该 Slave 连接的位于同一区域和集群中的 Master 的 RSocket 服务端端口。 |
||
| 10 | 该 Slave 连接的位于同一区域和集群中的 Master 的 RSocket 服务端主机地址。 |
基于 Kubernetes StatefulSet 的自动化角色识别
在 Kubernetes 上部署集群化 Ring-Coordinator 时,为 Master(stacksaga.coordinator.instance-type=master)和 Slave(stacksaga.coordinator.instance-type=slave)分别配置独立的 Deployment 会增加额外的运维负担。
因此,官方推荐将 Ring-Coordinator 集群部署为 Kubernetes StatefulSet。
在 StatefulSet 中,每个 Pod 会获得一个确定性的、带序号索引的主机名:
<statefulset-name>-0 (例如:ring-coordinator-0) <statefulset-name>-1 (例如:ring-coordinator-1) <statefulset-name>-2 (例如:ring-coordinator-2)
StackSaga 通过 stacksaga.coordinator.deploy.index-based 配置属性,能够直接根据该序号索引自动判定协调器的角色:
-
Pod 索引为
0:自动指定为master节点。 -
Pod 索引
> 0(例如索引 1, 2, …):自动指定为slave节点。
开启基于索引的角色判定
要启用自动角色识别,只需设置 stacksaga.coordinator.deploy.index-based=true:
# 为 Kubernetes StatefulSet 启用基于索引的角色自动识别
stacksaga.coordinator.deploy.index-based=true (1)
# 可选项:无需显式设置 instance-type,系统会自动推导 (2)
# 该集群协调的目标服务列表
stacksaga.coordinator.target-services=order-service,payment-service (3)
# RSocket 服务端配置
spring.rsocket.server.port=7777 (4)
spring.rsocket.server.transport=tcp
# 目标 Master 连接配置(当索引 > 0 时供 Slave Pod 使用)
stacksaga.coordinator.slave.target-master.host=ring-coordinator-0.ring-coordinator-headless (5)
stacksaga.coordinator.slave.target-master.port=7777 (6)
# 集群与区域元数据
stacksaga.instance.cluster=cluster1
stacksaga.instance.region=us-east-1
stacksaga.instance.zone=us-east-1a
| 1 | 开启基于序号索引的自动化角色识别。 |
| 2 | stacksaga.coordinator.instance-type 变为可选。Pod 0 自动作为 master 运行,而 Pod 1..N 自动作为 slave 运行。 |
| 3 | 该环协调器集群负责协调的微服务。 |
| 4 | 用于节点通信的 RSocket 端口。 |
| 5 | Master Pod(即 Pod 0)的主机名。在 Kubernetes 中,通常指向 Master Pod 的 Headless Service DNS(例如 <statefulset-name>-0.<headless-service-name>)。当 Pod 0 作为 Master 启动时会忽略此属性;当 Pod 1..N 作为 Slave 启动时,会通过此地址连接到 Pod 0。 |
| 6 | Master Pod 的端口。 |
Pod 标识符解析优先级顺序
当配置了 stacksaga.coordinator.deploy.index-based=true 时,StackSaga 会按以下顺序依次检查数据源以提取 Pod 序号索引:
-
stacksaga.coordinator.instance-id(在配置中显式指定的覆盖值) -
POD_NAME(标准的 Kubernetes Downward API 环境变量) -
HOSTNAME(标准的 Kubernetes Pod 主机名环境变量)
数字索引从最后一个连字符 (-) 之后的后缀中提取,并自动忽略任何 FQDN 域名后缀(例如 ring-coordinator-0.ring-coordinator-headless.default.svc.cluster.local 会准确解析出索引 0)。
|
在标准的 Docker 容器和独立的 Linux 环境中, |
配置属性参考手册 (Configuration Properties Reference)
下表汇总了重试环协调器的所有配置属性。第一组适用于 master 和 slave 实例;第二组仅适用于 slave 实例。
默认值 (Default) 列中显示连字符 (-) 的属性为必填项且无默认值,必须显式指定。
|
| 属性名称 (Property Name) | 默认值 (Default) | 类型 (Type) | 描述 (Description) |
|---|---|---|---|
通用配置 — 适用于 Master 和 Slave 实例 |
|||
|
|
|
协调器实例角色( |
|
- |
|
该实例运行的角色—— |
|
- |
|
该实例负责处理的服务名称(逗号分隔列表)。Master 用它来判断哪些 Slave 可以连接;Slave 用它来决定连接哪一个 Master。Slave 支持的每个服务都必须包含在对应 Master 的支持列表中,否则连接将被拒绝;但 Master 支持的服务集可以多于任何单个 Slave。 |
|
- |
|
内嵌 RSocket 服务端绑定的端口。Slave 在该端口上连接 Master,Orchestrator 也在该端口上连接 Slave,因此该端口同时服务这两种连接类型。 |
|
- |
|
内嵌 RSocket 服务端绑定的网络地址。 |
|
- |
|
内嵌 RSocket 服务端的传输层协议。对于重试环协调器服务必须为 |
|
- |
|
该实例所属的集群标识。仅当组件的 |
|
|
|
该实例所属的区域标识。若 |
|
- |
|
该实例所属的可用区标识。在此处对重试功能没有实际影响,但应按照 StackSaga 规范进行设置。 |
Slave 独有配置 — 仅适用于 |
|||
|
- |
|
该 Slave 连接的 Master 主机地址(位于同一区域和集群内)。用于建立从 Slave 到 Master 的 RSocket 连接。 |
|
- |
|
该 Slave 连接的 Master 端口号(位于同一区域和集群内)。用于建立从 Slave 到 Master 的 RSocket 连接。 |
|
|
|
与 Master 建立连接时 TCP 重连尝试的最大次数。如果在达到此重试上限后 Slave 仍无法连通,实例将自行终止退出。 |
|
|
|
TCP 重连尝试之间的初始退避时间。尝试失败后,Slave 等待该时长再重试,后续每次尝试将递增,直到达到 |
|
|
|
TCP 重连退避时间的上限值。两次重连尝试之间递增的等待时间绝不会超过该值。 |
|
|
|
放弃前 RSocket 流重试尝试的最大次数。该参数控制 RSocket 数据流本身的恢复,与上方的 TCP |
|
|
|
RSocket 流重试尝试之间的初始退避时间。尝试失败后,Slave 等待该时长再重试,后续每次尝试将递增,直到达到 |
|
|
|
RSocket 流重试退避时间的上限值。两次重试尝试之间递增的等待时间绝不会超过该值。 |
|
|
|
应用于 RSocket 流重试退避时间的抖动因子 (Jitter)。对退避时间进行随机化抖动可以有效防止大量 Slave 同时向 Master 发起重连时引发的惊群效应 (Thundering-Herd Problem)。取值必须在 |
|
|
|
控制当 Orchestrator 向 Master 查询可用 Slave 时,Master 返回的地址类型。设置为 |