想必看到此文的开发大佬们都在开发中或多或少的使用过重试, 比如接口超时重试、分布式锁获取失败重试等等使用场景.
常规的重试模式如下
重试风险
可以说绝大数情况都是可以使用本地重试就能解决,比如网络抖动、获取分布式锁失败等等,但是这类重试往往是短时瞬间的,可能发生以下情况
如图所示服务间调用链
若C请求D发生异常则会导致整个调用链全部失败,假设每个节点都重试3次那么C节点的所收到的请求量是:
A服务发起的请求: 9 次数,B服务发起的请求: 3 次 共计:27次。如果放大重试次数或者放大链路的长度,那么C服务几乎等价于被DDOS一样, 正常的请求流量也会被影响。 其实很少人会考虑这么多, 如果你是一个基础服务,出于对系统的稳定性考虑,就不得不考虑一下哪些是重试流量哪些是正常的请求,避免影响正常的业务流程。
总结: 这就是重试风暴带来危害。
EasyRetry的分布式重试就是为了解决此类问题,让重试更安全、数据可管理、风险可管控、丰富的告警场景。
能力展示
具有丰富功能的注解
100%可以满足日常的开发述求,比如所属
public @interface Retryable {
/**
* 场景值
*/
String scene();
/**
* 包含的异常
*/
Class<? extends Throwable>[] include() default {};
/**
* 排除的异常
*/
Class<? extends Throwable>[] exclude() default {};
/**
* 重试策略
*/
RetryType retryStrategy() default RetryType.LOCAL_REMOTE;
/**
* 重试处理入口,默认为原方法
*
*/
Class<? extends ExecutorMethod> retryMethod() default ExecutorAnnotationMethod.class;
/**
* 幂等id生成器
* 同一个组的同一个场景下只会存在一个相同的idempotentId并且状态为'重试中'的任务, 若存在相同的则上报服务后会被幂等处理
* 比如:
* 组: AGroup
* 场景: BScene
* 时刻1: 上报一个异常 idempotentId: A1 状态为重试中
* 时刻2: 上报一个异常 idempotentId: A2 状态为重试中,可以上报成功,此时存在两个重试任务
* 时刻3: 上报一个异常 idempotentId: A1 不会新增一个重试任务,会被幂等处理
* 时刻4: idempotentId: A1 重试完成, 状态为已完成
* 时刻5: 上报一个异常 idempotentId: A1 状态为重试中, 新增一条重试任务
* <p>
* 默认的idempotentId生成器{@link SimpleIdempotentIdGenerate} 对所有参数进行MD5
*
* @return idempotentId
*/
Class<? extends IdempotentIdGenerate> idempotentId() default SimpleIdempotentIdGenerate.class;
/**
* 服务端重试完成(重试成功、重试到达最大次数)回调客户端
*
*/
Class<? extends RetryCompleteCallback> retryCompleteCallback() default SimpleRetryCompleteCallback.class;
/**
* 用于标识具有业务特点的值, 比如订单号、物流编号等,可以根据具体的业务场景生成,生成规则采用通用成熟的Spel表达式进行解析
*
* see: <a href="https://docs.spring.io/spring-framework/docs/5.0.0.M5/spring-framework-reference/html/expressions.html">...</a>
*/
String bizNo() default "";
/**
* 本地重试次数 次数必须大于等于1
*/
int localTimes() default 3;
/**
* 本地重试间隔时间(s)
*/
int localInterval() default 2;
/**
* 本地重试完成后是否抛出异常
* 如果不抛出异常,则调用需要重试方法的方法则感知不到异常信息
*
* 比如: A->B->C->D->E
* D需要重试 若配置D不抛异常,则A->B->C无法感知,若有事物则无法回滚
*
* @return true-抛出 false-不抛出
*/
boolean isThrowException() default true;
/**
* 异步上报数据到服务端
*
* @return boolean
*/
boolean async() default true;
/**
* 同步(async:false)上报数据需要配置超时时间
*
* @return 超时时间
*/
long timeout() default 60 * 1000;
/**
* 超时时间单位
*
* @return TimeUnit
*/
TimeUnit unit() default TimeUnit.MILLISECONDS;
/**
* 重试传播机制
*
* @return Propagation
*/
Propagation propagation() default Propagation.REQUIRED;
}
重试流量可管控
单机重试管理
- 传播机制
- 自定义幂等策略
- 重试处理入口管理
- 幂等id生成
- ......
跨服务间管控
- 重试流量可以传递
- 下游可拒绝(返回特殊的status code)
后台重试数据管控
场景配置
重试数据
死信队列
告警场景多
- 支持企业微信、钉钉、飞书、邮箱通知类型
- 支持@ALL和@某人
- 自定义的阈值
- ....
欢迎大家接入使用Easy Retry,如果Easy Retry帮助到了你,请点个star 支持一下