Sentinel教程:06 高级规则之集群流控

介绍

集群流控可以精确地控制整个集群的调用总量,结合单机限流兜底,可以更好地发挥流量控制的效果。

集群流控中共有两种身份:

  • Token Client:集群流控客户端,用于向所属 Token Server 通信请求 token。集群限流服务端会返回给客户端结果,决定是否限流。
  • Token Server:即集群流控服务端,处理来自 Token Client 的请求,根据配置的集群规则判断是否应该发放 token(是否允许通过)。

模块结构

Sentinel 1.4.0 开始引入了集群流控模块,主要包含以下几部分:

  • sentinel-cluster-common-default: 公共模块,包含公共接口和实体
  • sentinel-cluster-client-default: 默认集群流控 client 模块,使用 Netty 进行通信,提供接口方便序列化协议扩展
  • sentinel-cluster-server-default: 默认集群流控 server 模块,使用 Netty 进行通信,提供接口方便序列化协议扩展;同时提供扩展接口对接规则判断的具体实现(TokenService),默认实现是复用 sentinel-core 的相关逻辑

集群流控规则

规则

FlowRule

  • 单机均摊模式下配置的阈值等同于单机能够承受的限额,token server 会根据客户端对应的 namespace(默认为 project.name 定义的应用名)下的连接数来计算总的阈值
  • 全局模式下配置的阈值等同于整个集群的总阈值

ParamFlowRule

  • 热点参数限流相关的集群配置与 FlowRule 相似

配置方式

在集群流控的场景下,我们推荐使用动态规则源来动态地管理规则。

对于客户端,我们可以按照原有的方式来向 FlowRuleManager 和 ParamFlowRuleManager 注册动态规则源。

ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId, parser);
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());

对于集群流控 token server,由于集群限流服务端有作用域(namespace)的概念,因此我们需要注册一个自动根据 namespace 生成动态规则源的 PropertySupplier。 然后每当集群限流服务端 namespace set 产生变更时,Sentinel 会自动针对新加入的 namespace 生成动态规则源并进行自动监听,并删除旧的不需要的规则源。

// Supplier 类型:接受 namespace,返回生成的动态规则源,类型为 SentinelProperty<List<FlowRule>>
// ClusterFlowRuleManager 针对集群限流规则,ClusterParamFlowRuleManager 针对集群热点规则,配置方式类似
ClusterFlowRuleManager.setPropertySupplier(namespace -> {
    return new SomeDataSource(namespace).getProperty();
});

集群限流客户端

要想使用集群限流功能,必须引入集群限流 client 相关依赖:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-cluster-client-default</artifactId>
    <version>1.8.6</version>
</dependency>

可以通过动态配置源进行配置。我们可以通过 ClusterClientConfigManager 的 registerServerAssignProperty 方法注册动态配置源。配置源注册的相关逻辑可以置于 InitFunc 实现类中,并通过 SPI 注册,在 Sentinel 初始化时即可自动进行配置源加载监听。

若用户未引入集群限流 client 相关依赖,或者 client 未开启/连接失败/通信失败,则对于开启了集群模式的规则:

  • 集群热点限流默认直接通过
  • 普通集群限流会退化到 local 模式的限流,即在本地按照单机阈值执行限流检查
  • 当 token client 与 server 之间的连接意外断开时,token client 会不断进行重试,每次重试的间隔时间以 n * 2000 ms 的形式递增

集群限流服务端

要想使用集群限流服务端,必须引入集群限流 server 相关依赖:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-cluster-server-default</artifactId>
    <version>1.8.6</version>
</dependency>

Sentinel 集群限流服务端有两种启动方式:

  • 独立模式(Alone),即作为独立的 token server 进程启动,独立部署,隔离性好,但是需要额外的部署操作。独立模式适合作为 Global Rate Limiter 给集群提供流控服务。
  • 嵌入模式(Embedded),即作为内置的 token server 与服务在同一进程中启动。在此模式下,集群中各个实例都是对等的,token server 和 client 可以随时进行转变,因此无需单独部署,灵活性比较好。但是隔离性不佳,需要限制 token server 的总 QPS,防止影响应用本身。嵌入模式适合某个应用集群内部的流控。

属性配置

推荐给集群限流服务端注册动态配置源来动态地进行配置。配置类型有以下几种:

  • namespace set: 集群限流服务端服务的作用域(命名空间),可以设置为自己服务的应用名。集群限流 client 在连接到 token server 后会上报自己的命名空间(默认为 project.name 配置的应用名),token server 会根据上报的命名空间名称统计连接数。
  • transport config: 集群限流服务端通信相关配置,如 server port
  • flow config: 集群限流服务端限流相关配置,如滑动窗口统计时长、格子数目、最大允许总 QPS等

注意:我们可以通过 ClusterServerConfigManager 的各个 registerXxxProperty 方法来注册相关的配置源。

注意:从 1.4.1 版本开始,Sentinel 支持给 token server 配置最大允许的总 QPS(maxAllowedQps),来对 token server 的资源使用进行限制,防止在嵌入模式下影响应用本身。

Token Server 分配配置

扩展接口设计

整体扩展架构

通用扩展接口

以下通用接口位于 sentinel-core 中:

  • TokenService: 集群限流功能接口,server / client 均可复用
  • ClusterTokenClient: 集群限流功能客户端
  • ClusterTokenServer: 集群限流服务端接口
  • EmbeddedClusterTokenServer: 集群限流服务端接口(embedded 模式)

以下通用接口位于 sentinel-cluster-common-default

  • EntityWriter
  • EntityDecoder

Client 扩展接口

集群流控 Client 端通信相关扩展接口:

  • ClusterTransportClient:集群限流通信客户端
  • RequestEntityWriter
  • ResponseEntityDecoder

Server 扩展接口

集群流控 Server 端通信相关扩展接口:

  • ResponseEntityWriter
  • RequestEntityDecoder

集群流控 Server 端请求处理扩展接口:

  • RequestProcessor: 请求处理接口 (request -> response)