基于流控策略的优雅退避机制
基于流控策略的优雅退避机制介绍。
新增重试机制(重试机制)及流控策略。
核心库 aliyun-java-sdk-core 从 4.6.0 版本开始支持重试机制(重试机制),以及提供基于流控策略的优雅退避方案。Maven 依赖如下:
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.6.0</version>
</dependency>
并非所有产品 API 都支持基于流控策略的优雅退避机制,具体有哪些支持可参考各个产品接口文档的流控信息一栏,例如:ECS 的 DescribeHpcClusters 接口文档:流控信息。
不管云产品的接口是否支持流控退避策略,您都可在 SDK 中设置开启流控退避机制,若接口不支持,则 SDK 的退避与静默管控则不生效,与不开启的状态一致。但请注意,该方式存在风险,可能存在接口某一天突然开启了流控退避的情况,导致您在调用中触发流控突然导致静默,增大排查难度。
请在开启流控退避策略之后,依然保持对调用异常的监控,不能完全依赖于流控退避策略,以此导致漏查风险的状况。
以下介绍,均是基于接口已支持流控退避的情况。
基于流控策略的优雅退避机制
基于流控策略的优雅退避,简单说分为两种策略:
重试退避策略
流控静默策略
重试机制中已讲,重试时间间隔是根据指数退避来的,使用的 EqualJitter(指数退避)算法计算出下次重试等待时间。除此之外,我们还提供了基于流控的优雅退避时间计算机制。
开启流控控制
默认关闭流控策略的控制,若要开启,则可使用以下两种方式:
配置 RetryPolicy
RetryPolicy retryPolicy = RetryPolicy.builder()
.maxNumberOfRetries(3) // 最大重试次数
.maxDelayTimeMillis(20 * 1000) // 最大重试间隔时间,单位为毫秒,超过这个时间则不再重试
//.retryConditions(retryConditions) // 触发重试策略
.enableAliyunThrottlingControl(true) // 使用阿里云流控策略进行控制
//.throttlingConditions(throttlingConditions) // 限制重试策略
.build();
request.setSysRetryPolicy(retryPolicy);
使用默认 RetryPolicy 策略
// 默认策略,入参为 enableAliyunThrottlingControl,true 表示开启,false 表示关闭
RetryPolicy retryPolicy = RetryPolicy.defaultRetryPolicy(
true
);
request.setSysRetryPolicy(retryPolicy);
开启流控控制的优势
减少不必要的重试,降低系统消耗
更加准确利用退避时间,优雅地进行重试
高阶
重试退避策略:基于流控策略下的退避时间计算
开启流控策略的控制能力后,退避时间计算逻辑为:
如果没有触发流控,就一直用EqualJitter计算重试时间间隔;
如果触发了流控,则取流控剩余时间和 EqualJitter 计算结果的最大值做时间间隔,时间如果大于最大重试时间间隔的限制,则直接抛异常,并且将流控剩余时间记录在缓存池中,以供流控静默策略使用。
流控静默策略
开启流控策略的控制能力后,当触发流控限制,服务端则会在返回头(Header)中返回流控剩余的 quota 信息,即针对【用户】维度、【API + 用户】维度,返回给客户端以下信息:API 调用剩余次数、限流剩余时间等。其中当被限流时,API 调用剩余次数则为 0。
两个维度在 Header 中对应的 Key 值为:
【API + 用户】维度:X-RateLimit-User-API
【用户】维度:X-RateLimit-User
针对【API + 用户】维度举例说明:
"X-RateLimit-User-API" : "Remain:1,Limit:2,Time:1000,TimeLeft:122,Reset:1637835220000"
Remain:剩余量,int 类型,如果为 -1,则表示剩余量足够;如果已经被流控,则返回0;
Limit:流控的阈值上限,int 类型
Time:流控的时间跨度,long 类型,单位毫秒
TimeLeft:本流控周期剩余时间,long 类型,单位毫秒
Reset:流控下一次周期开始时间,long 类型,毫秒时间戳
而 SDK 会对流控剩余时间进行管理,在这个时间段里,若发起调用或者重试调用将会受到限制,如果这个时间大于最大重试间隔时间,则直接抛错,若不大于最大间隔重试时间,则会静默等待直到允许发起调用或重试。
开启流控调试
在能力开启的条件下,除了遇到流控限制的情况会返回 Header 中的流控剩余的 quota 信息外,还可以在正常调用时要求返回该 quota 信息,只需要在请求头中加 X-RateLimit-Mode
字段值为 debug
即可:
request.putHeadParameter("X-RateLimit-Mode", "debug");
这样就会在每次接口调用的返回头中拿到剩余 quota 信息。