From 850b133db9a6d87dbb8cdf8111ac7a27b3fdebd5 Mon Sep 17 00:00:00 2001 From: "www.byteblogs.com" <598092184@qq.com> Date: Thu, 20 Apr 2023 17:12:23 +0800 Subject: [PATCH] =?UTF-8?q?feat:=201.0.0=20=E6=9B=B4=E6=96=B0readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 456 +++--------------------------------------- doc/images/aizuda.png | Bin 0 -> 21962 bytes doc/images/logo.png | Bin 0 -> 8890 bytes 3 files changed, 30 insertions(+), 426 deletions(-) create mode 100644 doc/images/aizuda.png create mode 100644 doc/images/logo.png diff --git a/README.md b/README.md index 88075684a..84a24ec76 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,15 @@ -## 《分布式重试服务平台 easy-retry》 + + +

+ + Easy-Retry-Logo + +

+ +

+ 分布式重试服务平台 Easy-Retry +

+ # 简介 >在分布式系统大行其道的当前,系统数据的准确性和正确性是重大的挑战,基于CAP理论,采用柔性事务,保障系统可用性以及数据的最终一致性成为技术共识 @@ -20,442 +31,35 @@ > + 打包上报,支持高并发业务场景 > + 加密通讯,保障信息安全 - # 流量管理平台预览 地址: 账号: admin 密码: admin -# 官方QQ群 -使用过程中有任何问题,或者对项目有什么想法或者建议,可以加入社群,跟群友一起交流讨论 -![qq.png](doc/images/qq.png) +## 特别用户 +![aizuda.png](doc/images/aizuda.png) -# 特性 -1. 管控重试流量,预防重试风暴,及早发现和预警,并且提供流程管理手段 -2. 保证易用性: 业务接入成本小。避免依赖研发人员的技术水平,保障重试的稳定性 -3. 灵活性: 能够动态调整配置,启动/停止任务,以及终止运行中的重试数据 -4. 操作简单:一分钟上手,支持WEB页面对重试数据CRUD操作。 -5. 数据大盘: 实时管控系统重试数据。 -6. 多样化退避策略: Cron、固定间隔、等级触发、随机时间触发 -7. 容器化部署: 服务端支持docker容器部署 -8. 高性能调度平台: 支持服务端节点动态扩容和缩容 -9. 多样化重试类型: 支持ONLY_LOCAL、ONLY_REMOTE、LOCAL_REMOTE多种重试类型 -10. 重试数据管理: 可以做到重试数据不丢失、重试数据一键回放 -11. 支持多样化的告警方式: 邮箱、企业微信、钉钉 +## 相关链接 +- [字节跳动: 如何优雅地重试](https://juejin.cn/post/6914091859463634951) +- [文档]() +- [功能实例]() +## 原理 +- [客户端原理剖析](https://gitee.com/aizuda/easy-retry/tree/dev/example) +- [服务端原理剖析](https://gitee.com/aizuda/easy-retry/tree/dev/example) -# 快速入门 -## 添加依赖 -```java +## 应用实例 +- [Spring-Boot](https://gitee.com/aizuda/easy-retry/tree/dev/example) + +``` com.aizuda easy-retry-client-starter - 最新版本 + 1.0.0 ``` -## 配置 -添加注解开启easy-retry功能 -```java -@SpringBootApplication -@EnableXRetry(group = "example_group") -public class ExampleApplication { - - public static void main(String[] args) { - SpringApplication.run(ExampleApplication.class, args); - } - -} -``` - -为需要重试的方法添加重试注解 -```java -@Retryable(scene = "errorMethodForLocalAndRemote", localTimes = 3, retryStrategy = RetryType.LOCAL_REMOTE) - public String errorMethodForLocalAndRemote(String name) { - - double i = 1 / 0; - - return "这是一个简单的异常方法"; - } -``` - -## Retryable 详解 -|属性|类型|必须指定|默认值|描述| -|-|-|-|-|-| -| scene |String|是|无|场景| -| include | Throwable |否|无|包含的异常| -| exclude |Throwable|否|无|排除的异常| -| retryStrategy|RetryType|是|LOCAL_REMOTE|重试策略| -| retryMethod|RetryMethod|是|RetryAnnotationMethod|重试处理入口| -| bizId | BizIdGenerate |是| SimpleBizIdGenerate |自定义业务id,默认为hash(param),传入成员列表,全部拼接取hash| -| retryCompleteCallback | RetryCompleteCallback |否| SimpleRetryCompleteCallback |服务端重试完成(重试成功、重试到达最大次数)回调客户端| -| isThrowException|boolean|否|true| 本地重试完成后是否抛出异常 | -| bizNo |String|否|无| bizNo spel表达式| -| localTimes |int|是|3| 本地重试次数 次数必须大于等于1| -| localInterval |int|是|2| 本地重试间隔时间(s)| - - -## 配置部署服务端调度平台 -### 初始化数据库 -数据库脚本位置 -``` -doc/sql/x_retry.sql -``` - -### 系统配置 -```yaml -spring: - datasource: - name: easy_retry - url: jdbc:mysql://localhost:3306/x_retry?useSSL=false&characterEncoding=utf8&useUnicode=true - username: root - password: root - type: com.zaxxer.hikari.HikariDataSource - driver-class-name: com.mysql.jdbc.Driver - hikari: - connection-timeout: 30000 - minimum-idle: 5 - maximum-pool-size: 20 - auto-commit: true - idle-timeout: 30000 - pool-name: easy_retry - max-lifetime: 1800000 - connection-test-query: SELECT 1 - resources: - static-locations: classpath:admin/ -mybatis-plus: - mapper-locations: classpath:/mapper/*.xml - typeAliasesPackage: com.x.retry.server.persistence.mybatis.po - global-config: - db-config: - field-strategy: NOT_EMPTY - capital-mode: false - logic-delete-value: 1 - logic-not-delete-value: 0 - configuration: - map-underscore-to-camel-case: true - cache-enabled: true -easy-retry: - lastDays: 30 # 拉取重试数据的天数 - retryPullPageSize: 100 # 拉取重试数据的每批次的大小 - nettyPort: 1788 # 服务端netty端口 - totalPartition: 32 # 重试和死信表的分区总数 - -``` - -##项目部署 -### 下载源码部署 -- 下载源码 - ``` - https://github.com/byteblogs168/easy-retry.git - ``` - -- maven 打包镜像 -``` -maven clean install -``` - -- 修改配置 -``` -/easy-retry-server/src/main/resources/application.yml -``` - -- 启动 -``` -java -jar easy-retry-server.jar -``` - -### docker 部署 -- 下载镜像 - 地址: https://github.com/byteblogs168/easy-retry/pkgs/container/easy-retry-server - ``` - docker pull ghcr.io/byteblogs168/easy-retry-server:{最新版本} - ``` - -- 创建容器并运行 - -``` -/** -* 如需自定义 mysql 等配置,可通过 "-e PARAMS" 指定,参数格式 PARAMS="--key1=value1 --key2=value2" ; -* 配置项参考文件:/easy-retry-server/src/main/resources/application.yml -* 如需自定义 JVM内存参数 等配置,可通过 "-e JAVA_OPTS" 指定,参数格式 JAVA_OPTS="-Xmx512m" ; -*/ -docker run \ - -e PARAMS="--spring.datasource.username=root --spring.datasource.password=123456 --spring.datasource.url=jdbc:mysql://ip:3306/x_retry?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai " \ - -p 8080:8080 \ - -p 1788:1788 \ - --name easy-retry-server-1 \ - -d registry.cn-shanghai.aliyuncs.com/byteblogs/easy-retry:{最新版本} - -``` - -如果你已经正确按照系统了,那么你可以输入 -``` -http://localhost:8080 -``` - -会出现登陆页面: - -![login.png](doc/images/login.png) - -输入用户名: admin, 密码: 123456 - -## 仪表板 -仪表盘直观展示系统的任务量、调度量、在线节点展示等 -### 总任务量 -统计当前系统总的任务量 -#### 完成 -已经调度成功的异常数据 -#### 运行中 -处于调度中的异常数据 -#### 最大次数 -调度次数超过配置的最大执行次数的异常数据 - -### 总调度量 -展示系统触发调度的总数量 -#### 失败 -包括调度客户端执行失败、调度超时等异常执行的数据 -#### 成功 -调用客户端执行重试成功的数据 - -### 总在线机器 -实时展示当前活跃的客户端与服务端 - -![dashboard.png](doc/images/dashboard.png) - - -## 组配置 -通过`新建`按钮配置点开配置组、场景、通知界面 -![group_list.png](doc/images/group_list.png) - -### 组配置 -每个系统对应一个组,服务端通过一致性hash环来分配当前已启用的Group在集群中哪节点上消费 - -- 组名称: 名称是数字、字母、下划线组合,最长64个字符长度 -- 状态: 开启/关闭, 通过状态开启或关闭组状态 -- 路由策略: 随机算法、一致性hash算法、最近最久未使用算法 -- 描述: 对组进行描述 -- 指定分区: 不指定则系统随机分区,指定则使用指定的分区 - -![goup_config.png](doc/images/goup_config.png) - -### 场景配置 -场景负责管理收集重试现场的数据,比如 方法名、参数、类等信息; 对照代码 中可以理解为需要重试的方法; -每个业务服务对应N个场景值,即系统配置的最小单位。 - -- 场景名称: 名称是数字、字母、下划线组合,最长64个字符长度 -- 场景状态: 开启/关闭, 通过状态开启或关闭场合状态 -- 退避策略: 延迟等级、固定时间、CRON表达式、随机等待 -- 最大重试次数: 重试上限值 -- 描述: 对场景进行描述 -- 操作: 新增-添加场景配置、删除-未提交则删除临时场景配置,已提交则删除数据库中的场景配置 - -![scene_config.png](doc/images/scene_config.png) - -### 通知配置 -及时告知系统管理人员,系统运行状态,如出现大量重试的数据、或者大量重试失败的数据 - -- 通知类型: 钉钉通知、邮箱通知、企业微信通知 -- 通知场景: - - 重试数量超过阈值: 作用于服务端,重试中的数量到达阈值发送通知 - - 重试失败数量超过阈值: 作用于服务端,达到最大重试次数的数量到达阈值发送通知 - - 客户端上报失败: 作用于客户端,上报数据失败 发送 通知 - - 客户端组件异常: 作用于客户端,重试组件内部异常,发送通知 -- 通知阈值: 到达阈值发送通知 -- 通知地址: 发送通知的地址 -- 描述: 对通知进行描述 -- 操作: 新增-添加场景配置、删除-未提交则删除临时通知配置,已提交则删除数据库中的通知配置 - -![notify_config.png](doc/images/notify_config.png) - -### 重试列表 -查询当前处理重试中的数据,存在三种状态 -- 重试中: 会一直存在重试列表中 -- 最大重试次数: 重试失败次数到达最大重试次数之后,由清除线程负责迁移至死信队列列表中 -- 重试完成: 重试成功之后,由清除线程负责删除重试完成的数据 - -支持的搜索条件: -- 组名称: 下拉选择相应的组进行精确搜索 -- 场景名称: 下拉选择相应的场景进行精确搜索 -- 业务编号: 根据业务编号精确搜索 -- 业务id: 根据业务id精确搜索 - -![retry_task_list.png](doc/images/retry_task_list.png) - -### 重试日志列表 -支持的搜索条件: -- 组名称: 下拉选择相应的组进行精确搜索 -- 场景名称: 下拉选择相应的场景进行精确搜索 -- 业务编号: 根据业务编号精确搜索 -- 业务id: 根据业务id精确搜索 - -![retry_log_list.png](doc/images/retry_log_list.png) - -### 死信队列列表 -支持的搜索条件: -- 组名称: 下拉选择相应的组进行精确搜索 -- 场景名称: 下拉选择相应的场景进行精确搜索 -- 业务编号: 根据业务编号精确搜索 -- 业务id: 根据业务id精确搜索 - -#### 回滚 -死信队列数据迁移至重试任务重,并删除死信队列数据 - -![retry_dead_letter_list.png](doc/images/retry_task_dead_letter.png) - -### 用户列表 -搜索系统用户信息 -支持的搜索条件: -- 用户名: 模糊搜索用户名 - -![user_list.png](/doc/images/user_list.png) - -### 新增用户 -为系统新增用户 -- 用户名: 用户名是数字、字母、下划线组合,最长64个字符长度 -- 密码: 密码是数字、字母、下划线组合,最长64个字符长度 -- 角色: - - 普通用户: 负责分配的组权限 - - 管理员: 管理所有的 组谦虚 -- 权限: 需要管理的组 -![user_add.png](doc/images/user_add.png) - -### 系统剖析 -#### 客户端与服务端数据交互图 -![client_server_data_flow.jpg](doc/images/client_server_data_flow.jpg) - -> 客户端核心能力 -- 负责发现异常,标记事故现场 -- 根据不同阶段进行本地重试和远程重试 -- 失败上报和执行服务端下发的重试指令 -- 避免服务间调用产生重试放大风险 -- 重试流量管控 - - 单机多注解循环引用问题 - - 标记重试流量 - - 调用链超时控制(Deadline Request) - - 特殊的 status code 限制链路重试 - -> 服务端核心能力 -- 收集上报信息,统一预警 -- 通过组协调器为不同的POD分配需要调度的Group信息 -- 管理死信队列和重试数据状态以及触发时间 -- 支持配置中心可视化 - -#### 系统架构图 -![系统架构图-v1.0.jpg](doc/images/系统架构图-v1.0.jpg) - -### 客户端剖析 -#### 重试流量管控 -> 单机重试管控 - -单机多注解嵌套方法,通过标记重试现场入口,发生异常重试只重试现场入口,防止每个方法都重试, 从而避免了重试风暴 - -> 链路重试管控 - -- 特殊的status code限制链路重试: 让被调用方有反抗的权利(统一约定一个特殊的 status code -它表示:调用失败,但别重试) -- 调用链超时控制(Deadline Request): 当剩余时间不够时不再发起重试请求 -- 特殊的retry flag 保障重试请求不重试: 通请求头传递retry flag 保障即使发生异常也不重试 - -> 重试流速管控 - -通过路由策略和限流措施对每个组的集群进行流量控制 - -#### 支持多种退避策略 -- 线性退避: 每次等待固定时间后重试 -- 随机退避: 在一定范围内随机等待一个时间后重试 -- 延迟等级退避: 依据延迟等级, 等待每个延迟等级设置的时间, 延迟等级枚举 `DelayLevelEnum` -- Cron表达式退避: 使用Cron表达式计算重试触发时间 - -#### 客户端功能模块图 -![客户端功能模块-v1.0.jpg](doc/images/客户端功能模块-v1.0.jpg) - -- 启动模块 - - 滑动窗口模块: 监听需要上报的数据 - - Netty启动器: 启动客户端Netty组件,建立与服务端心跳机制 - - 远程配置获取器: 获取最新版本的配置信息 - - 注解扫描模块: 负责扫描添加到方法上的@Retryable注解,获取参数信息、类信息、方法路径等;解析注解元数据信息,构建执行器 - -- 重试阶段 - - 重试模式 - - 本地重试: 当发生异常时候, 若注解上的配置`RetryType.ONLY_LOCAL`或者`RetryType.LOCAL_REMOTE`, 则会触发本地内存重试 - - 远程重试: 本地重试没有成功,若注解上的配置`RetryType.ONLY_REMOTE`或者`RetryType.LOCAL_REMOTE`, 则会触发上报服务端重试 - - - 执行器 - - 重试组件: 对guava retry 的深度封装 - - 重试执行器 - - 类反射执行器: 即重试执行原方法 - - 自定义方法执行器: 用户通过实现`RetryMethod`接口, 即可实现自定义重试, 发生重试时直接重试自定义方法执行器 -- 重试流量管控 - - 单机多注解循环引用问题 - > 标记重试入口,触发重试时只从标记的重试入口进入 - - ![单机多注解循环引用问题.jpg](doc/images/单机多注解循环引用问题.jpg) - - - 标记重试流量 - > 对于重试的请求,我们在请求头中下发一个特殊的标识(xRetry:boolean), - 在 Service A ->Service B ->Service C 的调用链路中,当Service B 收到Service A 的请求时会先读取这个 xRetry 判断这个请求是不是重试请求, - 如果是,那它调用Service C 即使失败也不会重试;否则将触发重试 。 - 同时Service B 也会把这个 xRetry 下传,它发出的请求也会有这个标志,它的下游也不会再对这个请求重试 - - ![重试流量标识.jpg](doc/images/重试流量标识.jpg) - - - 调用链超时控制(Deadline Request) - > DDL 是“ Deadline Request 调用链超时”的简称,我们知道 TCP/IP 协议中的 TTL 用于判断数据包在网络中的时间是否太长而应被丢弃,DDL 与之类似, - 它是一种全链路式的调用超时,可以用来判断当前的 RPC 请求是否还需要继续下去。如下图,在 RPC 请求调用链中会带上超时时间, - 并且每经过一层就减去该层处理的时间,如果剩下的时间已经小于等于 0 ,则可以不需要再请求下游,直接返回失败即可。 - ![DDL.jpg](doc/images/DDL.jpg) - - - 特殊的 status code 限制链路重试 - > 如果每层都配置重试可能导致调用量指数级扩大,这样对底层服务来说压力是非常之大的, 通过对流量的标记 - ,用户可以判断是否是重试的流量来判断是否继续处理,我们使用 Google SRE 中提出的内部使用特殊错误码的方式来实现: - - 1 统一约定一个特殊的 status code ,它表示:调用失败,但别重试。 - 2 任何一级重试失败后,生成该 status code 并返回给上层。 - 3 上层收到该 status code 后停止对这个下游的重试,并将错误码再传给自己的上层。 - - > 这种方式理想情况下只有最下一层发生重试,它的上游收到错误码后都不会重试,但是这种策略依赖于业务方传递错误码, - 对业务代码有一定入侵,而且通常业务方的代码差异很大, 调用 RPC 的方式和场景也各不相同,需要业务方配合进行大量改造, - 很可能因为漏改等原因导致没有把从下游拿到的错误码传递给上游。 - - ![重试特殊的statuscode.jpg](doc/images/重试特殊的statuscode.jpg) - -### 服务端剖析 -#### 分布式调度模块 - -- master thread - 1. 扫描所有启用的组,通过客户端协调算法,分配当前节点需要重试的组 - 2. 生成Actor,并扫描当前分配组下面所有待重试的数据 - -- 重试分发组件 - - ScanGroupActor - 1. 通过配置的时间范围扫描待重试数据 - 2. 通过条件过滤器,过滤出满足条件的重试数据 - - - ExecUnitActor - 1. 通过远程调用下发重试指令, - 2. 标记重试流量 - - - 结果处理 - 1. FailureActor: 处理重试失败数据,累加重试次数 - 2. FinishActor: 处理重试成功数据并更新状态为重试成功 - -- 算法 - - 客户端轮询算法 - 1. 一致性Hash算法 - 2. LRU算法 - 3. 随机算法 - - 服务端Rebalance算法 - 1. 一致性hash 算法 - - - - - - - - - - - - +## 期望 +欢迎提出更好的意见,帮助完善 Easy-Retry +## 版权 +[GNU General Public License v3.0](https://gitee.com/aizuda/easy-retry/blob/0.0.4.3/LICENSE) \ No newline at end of file diff --git a/doc/images/aizuda.png b/doc/images/aizuda.png new file mode 100644 index 0000000000000000000000000000000000000000..bfbfc0da90d17fa6ecf427bcafbb063d5d2ef728 GIT binary patch literal 21962 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μ-CZ?AYAEju({cYr1rOJXpNPb6b7aAEI!deqr2&%>f zQM6ebbEE$_O5#2ysTq-`jhMM5lt32&oFA{rZRBVLQlPV+a6u999E{d-6US{r`9#De zB0{3`m)^T=@$+Im2%f$IbwdJ#8=N=AzCi zFNA<1$ND4mTc1EUmciXFC`z?S!k=kl3eFf>s26XsyXAv{w4XpOA_I|jI=D+kmevV# zjD9M>C-=^(RLKgB|E!KV5*jCN z5KWjabe0aGAu3ufcb^~Oy6(;;l5F#TTj|PclY+HK9YJRMz4MJ-P{dtI1@Y}7qNF}c z?&Cc5wd^{ikLxrQ($2!{RA42w`iB(qg6wGTN|h>As#K|RSmgf$x0wx7ep4WM00000NkvXXu0mjf5n`LP literal 0 HcmV?d00001 diff --git a/doc/images/logo.png b/doc/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b31e902274a9297fddba381de7752c8194bdc9bd GIT binary patch literal 8890 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 O0D4-+nsqSym;VQ6)uY+~ literal 0 HcmV?d00001