Spring Boot集成Resilience4J实现限流/重试/隔离

Spring Boot集成Resilience4J实现限流/重试/隔离

1.前言

上篇文章讲了Resilience4J实现熔断功能,文章详见:http://www.liuhaihua.cn/archives/711028.html,本篇文章主要讲述基于Resilience4J实现限流/重试/隔离。

2.代码工程

pom.xml

<dependency>    <groupId>io.github.resilience4jgroupId>    <artifactId>resilience4j-spring-boot3artifactId>    <version>2.0.2version>dependency><dependency>    <groupId>org.projectlombokgroupId>    <artifactId>lombokartifactId>dependency><dependency>    <groupId>org.springframework.bootgroupId>    <artifactId>spring-boot-starter-aopartifactId>dependency><dependency>    <groupId>org.springframework.bootgroupId>    <artifactId>spring-boot-starter-actuatorartifactId>dependency>

限流

@RequestMapping("/hello")@RateLimiter(name="ratelimitApi",fallbackMethod = "fallback")public ResponseEntity showHelloWorld(){   return new ResponseEntity<>("success",HttpStatus.OK);   }public ResponseEntity fallback(Throwable e){   log.error("fallback exception , {}",e.getMessage());   return new ResponseEntity<>("your request is too fast,please low down", HttpStatus.OK);}

重试

@RequestMapping("/retry")@Retry(name = "backendA")//use backendA ,if throw IOException ,it will be retried 3 times。public ResponseEntity<String> retry(String name){   if(name.equals("test")){      i++;      log.info("retry time:{}",i);      throw  new HttpServerErrorException(HttpStatusCode.valueOf(101));   }   return new ResponseEntity<>("retry",HttpStatus.OK);}

隔离

@RequestMapping("/bulkhead")@Bulkhead(name = "backendA")public ResponseEntity bulkhead(){
return new ResponseEntity<>("bulkhead",HttpStatus.OK);}

配置文件

spring:  application.name: resilience4j-demo  jackson.serialization.indent_output: true
management: endpoints.web.exposure.include: - '*' endpoint.health.show-details: always health.circuitbreakers.enabled: true
resilience4j: circuitbreaker: configs: default: registerHealthIndicator: true slidingWindowSize: 10 minimumNumberOfCalls: 5 permittedNumberOfCallsInHalfOpenState: 3 automaticTransitionFromOpenToHalfOpenEnabled: true waitDurationInOpenState: 5s failureRateThreshold: 50 eventConsumerBufferSize: 10

ratelimiter: instances: ratelimitApi: limit-for-period: 5 limit-refresh-period: 1s timeout-duration: 100ms retry: instances: backendA: maxAttempts: 3 waitDuration: 10s enableExponentialBackoff: true exponentialBackoffMultiplier: 2 retryExceptions: - org.springframework.web.client.HttpServerErrorException - java.io.IOException bulkhead: instances: backendA: maxConcurrentCalls: 10

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

  • https://github.com/Harries/springboot-demo(Resilience4J)

3.测试

1.启动Spring Boot应用程序

测试限流

public class ThreadTest {    public static void main(String[] args) {       for(int i=0;i<6;i++){            new Thread(()->{                System.out.println(new RestTemplate().getForObject("http://localhost:8080/hello",String.class));            }).start();        }         }}

运行main方法

io.github.resilience4j.bulkhead.BulkheadFullException: Bulkhead 'backendA' is full and does not permit further calls at io.github.resilience4j.bulkhead.BulkheadFullException.createBulkheadFullException(BulkheadFullException.java:49) ~[resilience4j-bulkhead-2.0.2.jar:2.0.2] at io.github.resilience4j.bulkhead.internal.SemaphoreBulkhead.acquirePermission(SemaphoreBulkhead.java:164) ~[resilience4j-bulkhead-2.0.2.jar:2.0.2] at io.github.resilience4j.bulkhead.Bulkhead.lambda$decorateCheckedSupplier$0(Bulkhead.java:68) ~[resilience4j-bulkhead-2.0.2.jar:2.0.2] at io.github.resilience4j.bulkhead.Bulkhead.executeCheckedSupplier(Bulkhead.java:471) ~[resilience4j-bulkhead-2.0.2.jar:2.0.2] at io.github.resilience4j.spring6.bulkhead.configure.BulkheadAspect.handleJoinPoint(BulkheadAspect.java:194) ~[resilience4j-spring6-2.0.2.jar:2.0.2] at io.github.resilience4j.spring6.bulkhead.configure.BulkheadAspect.proceed(BulkheadAspect.java:147) ~[resilience4j-spring6-2.0.2.jar:2.0.2] at io.github.resilience4j.spring6.bulkhead.configure.BulkheadAspect.lambda$bulkheadAroundAdvice$1(BulkheadAspect.java:120) ~[resilience4j-spring6-2.0.2.jar:2.0.2] at io.github.resilience4j.spring6.fallback.FallbackExecutor.execute(FallbackExecutor.java:37) ~[resilience4j-spring6-2.0.2.jar:2.0.2] at io.github.resilience4j.spring6.bulkhead.configure.BulkheadAspect.bulkheadAroundAdvice(BulkheadAspect.java:121) ~[resilience4j-spring6-2.0.2.jar:2.0.2] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:637) ~[spring-aop-6.1.2.jar:6.1.2]

测试重试

访问http://127.0.0.1:8080/retry?name=test

2024-08-03T23:16:32.092+08:00 INFO 5097 --- [resilience4j-demo] [nio-8080-exec-9] c.e.r.controller.HelloWorldController : retry time:12024-08-03T23:16:42.120+08:00 INFO 5097 --- [resilience4j-demo] [nio-8080-exec-9] c.e.r.controller.HelloWorldController : retry time:22024-08-03T23:17:02.142+08:00 INFO 5097 --- [resilience4j-demo] [nio-8080-exec-9] c.e.r.controller.HelloWorldController : retry time:32024-08-03T23:17:02.165+08:00 ERROR 5097 --- [resilience4j-demo] [nio-8080-exec-9] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.web.client.HttpServerErrorException: 101 SWITCHING_PROTOCOLS] with root cause
org.springframework.web.client.HttpServerErrorException: 101 SWITCHING_PROTOCOLS at com.et.resilience4j.controller.HelloWorldController.retry(HelloWorldController.java:37) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:352) ~[spring-aop-6.1.2.jar:6.1.2] at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.2.jar:6.1.2]

测试隔离

public class ThreadTest {    public static void main(String[] args) {      /*  for(int i=0;i<6;i++){            new Thread(()->{                System.out.println(new RestTemplate().getForObject("http://localhost:8080/hello",String.class));            }).start();        }*/      for(int i=0;i<11;i++){         new Thread(()->{            System.out.println(new RestTemplate().getForObject("http://localhost:8080/bulkhead",String.class));         }).start();      }    }}

运行main方法

2024-08-03T23:17:36.943+08:00 ERROR 5097 --- [resilience4j-demo] [nio-8080-exec-5] c.e.r.controller.HelloWorldController : fallback exception , RateLimiter 'ratelimitApi' does not permit further calls 


请使用浏览器的分享功能分享到微信等