Retry、CircuitBreaker、RateLimiter
(2)手动添加 Resilience4j 依赖 <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot2</artifactId> <version>1.5.0</version> </dependency> (3)把原来的 application.properties 文件删除,新建 application.yml 文件来配置 retry 重试,配置注册到 Eureka resilience4j: retry: retry-aspect-order: 399 #表示 retry 的优先级,默认高于限流、断路器,数值越小,优先级越高 backends: retryA: # 自定义策略 retryA maxRetryAttempts: 5 #重试次数 waitDuration: 500 #重试等待时间 exponentialBackoffMultiplier: 1.1 #间隔乘数,第一次 1.1秒,第二次 1.21 秒 retryExceptions: # 触发重试的异常 - java.lang.RuntimeException # 项目名及 eureka 配置 spring: application: name: resilience4j server: port: 5000 eureka: client: service-url: defaultZone: http://localhost:1111/eureka (4)在 provider 服务中,设置本身会抛异常的接口: public String hello(){ String s = "hello " + port; System.out.println(s); int i = 1/0; return s; } (5)resilience4j-2 服务中,创建 RestTemplate 请求模板 bean对象,创建 HelloService 和 HelloController 类 @SpringBootApplication public class Resilience4j2Application { public static void main(String[] args) { SpringApplication.run(Resilience4j2Application.class, args); } @Bean @LoadBalanced RestTemplate restTemplate(){ return new RestTemplate(); } } @Service @Retry(name="retryA")//表示使用的重试策略 public class HelloService { @Autowired RestTemplate restTemplate; public String hello(){ String s = restTemplate.getForObject("http://provider/hello", String.class); return s; } } @RestController public class HelloController { @Autowired HelloService helloService; @GetMapping("/hello") public String hello(){ return helloService.hello(); } }
在 HelloService 中的 @Retry(name = "retryA")注解的属性 retryA是在 application.yml中配置自定义的策略名;
(6)启动 Eureka 服务端、provider 服务和 resilience4j-2 服务,访问 http://localhost:5000/hello 地址: 前端报错 -(7)查看 provider 控制台日志,看接口中被访问情况: hello 1113 被打印了5次,说明接口被访问5次,就是说 resilience4j-2 的 retry 重试功能起作用了,重试了 5次。注意 error 方法的参数要加上Throwable参数,否则会报错,继续访问 hello 接口,返回 error ,说明服务降级了
在 provider 中,我们依然能看见 控制台打印 5次 hello 1113,证明 retry 也在起作用 (3)retry 和 circuitbreker 一起使用 在 provider 中更改接口,使请求重试在第二次成功, @RestController public class HelloController implements IUserService{ @Value("${server.port}") Integer port; @Override public String hello(){ String s = "hello " + port; System.out.println(s); if(port++ != 1114){ int i = 1/0; } return s; } }然后重启provider ,继续访问 hello 接口: 前端结果成功 provider 服务控制台日志 打印了两次,说明 retry 的第二次成功了,服务不进行降级。成功返回了结果 hello 1114
可以在请求端,也可以在被请求端使用,主要在被请求端使用,保护服务端的接口
(1)在 provider 中添加 Resilience4j 依赖 <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot2</artifactId> <version>1.5.0</version> </dependency> (2)在 application.properties 中配置限流 # 一个周期有几次请求 resilience4j.ratelimiter.instances.rlA.limit-for-period=2 # 一个周期的刷新时间 resilience4j.ratelimiter.instances.rlA.limit-refresh-period=1s resilience4j.ratelimiter.instances.rlA.timeout-duration=1s就是一秒处理两个请求
(3)修改 provider 中的 hello 接口,打印时间,方便观察限流效果 @RateLimiter(name = "rlA") public String hello(){ String s = "hello " + port; System.out.println(new Date()); return s; }@RateLimiter(name = "rlA")注解的 rlA是 application.properties中配置的自定义限流策略名称。
(4)在 resilience4j-2 中修改 HelloService 方法, 多次调用 provider 中的接口 @Service @Retry(name="retryA") @CircuitBreaker(name = "cbA",fallbackMethod = "error") public class HelloService { @Autowired RestTemplate restTemplate; public String hello(){ for (int i = 0;i < 5;i++){ String s = restTemplate.getForObject("http://provider/hello", String.class); } return "success"; } public String error(Throwable t){ return "error"; } } (5)重启 provider 和 resilience4j-2 服务,再次调用 http:///localhost:5000/hello,观察 provider 控制台打印情况: 如果修改 application.properties每秒处理一个请求 # 一秒处理一个请求 resilience4j.ratelimiter.instances.rlA.limit-for-period=1 resilience4j.ratelimiter.instances.rlA.limit-refresh-period=1s resilience4j.ratelimiter.instances.rlA.timeout-duration=1s再次查看 provider 的控制台 一秒处理一个请求也起了作用,这就是限流的简单应用
