From 8fb712241ab4cef2a3cf4e73374f456e4131c808 Mon Sep 17 00:00:00 2001
From: YunaiV <>
Date: Thu, 21 May 2020 08:22:19 +0800
Subject: [PATCH] =?UTF-8?q?resilience4j=20+=20=E7=9B=91=E6=8E=A7=20?=
=?UTF-8?q?=E7=A4=BA=E4=BE=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
lab-59/lab-59-resilience4j-actuator/pom.xml | 65 ++++++++++++++++++
.../resillience4jdemo/DemoApplication.java | 20 ++++++
.../controller/BulkheadDemoController.java | 30 +++++++++
.../controller/DemoController.java | 34 ++++++++++
.../controller/RateLimiterDemoController.java | 28 ++++++++
.../controller/RetryDemoController.java | 34 ++++++++++
.../ThreadPoolBulkheadDemoController.java | 49 ++++++++++++++
.../controller/TimeLimiterDemoController.java | 49 ++++++++++++++
.../src/main/resources/application.yml | 66 +++++++++++++++++++
lab-59/pom.xml | 1 +
pom.xml | 2 +-
11 files changed, 377 insertions(+), 1 deletion(-)
create mode 100644 lab-59/lab-59-resilience4j-actuator/pom.xml
create mode 100644 lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/DemoApplication.java
create mode 100644 lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/BulkheadDemoController.java
create mode 100644 lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/DemoController.java
create mode 100644 lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/RateLimiterDemoController.java
create mode 100644 lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/RetryDemoController.java
create mode 100644 lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/ThreadPoolBulkheadDemoController.java
create mode 100644 lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/TimeLimiterDemoController.java
create mode 100644 lab-59/lab-59-resilience4j-actuator/src/main/resources/application.yml
diff --git a/lab-59/lab-59-resilience4j-actuator/pom.xml b/lab-59/lab-59-resilience4j-actuator/pom.xml
new file mode 100644
index 00000000..9f7c4637
--- /dev/null
+++ b/lab-59/lab-59-resilience4j-actuator/pom.xml
@@ -0,0 +1,65 @@
+
+
+
+ lab-59
+ cn.iocoder.springboot.labs
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ lab-59-resilience4j-actuator
+
+
+ 1.8
+ 1.8
+ 2.2.4.RELEASE
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ ${spring.boot.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ io.github.resilience4j
+ resilience4j-spring-boot2
+ 1.4.0
+
+
+
+
+ org.aspectj
+ aspectjrt
+ 1.9.5
+
+
+ org.aspectj
+ aspectjweaver
+ 1.9.5
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+
diff --git a/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/DemoApplication.java b/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/DemoApplication.java
new file mode 100644
index 00000000..9f482e9d
--- /dev/null
+++ b/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/DemoApplication.java
@@ -0,0 +1,20 @@
+package cn.iocoder.springboot.lab59.resillience4jdemo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.client.RestTemplate;
+
+@SpringBootApplication
+public class DemoApplication {
+
+ @Bean
+ public RestTemplate restTemplate() {
+ return new RestTemplate();
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(DemoApplication.class, args);
+ }
+
+}
diff --git a/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/BulkheadDemoController.java b/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/BulkheadDemoController.java
new file mode 100644
index 00000000..6937108a
--- /dev/null
+++ b/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/BulkheadDemoController.java
@@ -0,0 +1,30 @@
+package cn.iocoder.springboot.lab59.resillience4jdemo.controller;
+
+import io.github.resilience4j.bulkhead.annotation.Bulkhead;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/bulkhead-demo")
+public class BulkheadDemoController {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+
+ @GetMapping("/get_user")
+ @Bulkhead(name = "backendC", fallbackMethod = "getUserFallback", type = Bulkhead.Type.SEMAPHORE)
+ public String getUser(@RequestParam("id") Integer id) throws InterruptedException {
+ logger.info("[getUser][id({})]", id);
+ Thread.sleep(10 * 1000L); // sleep 10 秒
+ return "User:" + id;
+ }
+
+ public String getUserFallback(Integer id, Throwable throwable) {
+ logger.info("[getUserFallback][id({}) exception({})]", id, throwable.getClass().getSimpleName());
+ return "mock:User:" + id;
+ }
+
+}
diff --git a/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/DemoController.java b/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/DemoController.java
new file mode 100644
index 00000000..37882518
--- /dev/null
+++ b/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/DemoController.java
@@ -0,0 +1,34 @@
+package cn.iocoder.springboot.lab59.resillience4jdemo.controller;
+
+import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+@RestController
+@RequestMapping("/demo")
+public class DemoController {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+
+ @Autowired
+ private RestTemplate restTemplate;
+
+ @GetMapping("/get_user")
+ @CircuitBreaker(name = "backendA", fallbackMethod = "getUserFallback")
+ public String getUser(@RequestParam("id") Integer id) {
+ logger.info("[getUser][准备调用 user-service 获取用户({})详情]", id);
+ return restTemplate.getForEntity("http://127.0.0.1:18080/user/get?id=" + id, String.class).getBody();
+ }
+
+ public String getUserFallback(Integer id, Throwable throwable) {
+ logger.info("[getUserFallback][id({}) exception({})]", id, throwable.getClass().getSimpleName());
+ return "mock:User:" + id;
+ }
+
+}
diff --git a/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/RateLimiterDemoController.java b/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/RateLimiterDemoController.java
new file mode 100644
index 00000000..51f1b561
--- /dev/null
+++ b/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/RateLimiterDemoController.java
@@ -0,0 +1,28 @@
+package cn.iocoder.springboot.lab59.resillience4jdemo.controller;
+
+import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/rate-limiter-demo")
+public class RateLimiterDemoController {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+
+ @GetMapping("/get_user")
+ @RateLimiter(name = "backendB", fallbackMethod = "getUserFallback")
+ public String getUser(@RequestParam("id") Integer id) {
+ return "User:" + id;
+ }
+
+ public String getUserFallback(Integer id, Throwable throwable) {
+ logger.info("[getUserFallback][id({}) exception({})]", id, throwable.getClass().getSimpleName());
+ return "mock:User:" + id;
+ }
+
+}
diff --git a/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/RetryDemoController.java b/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/RetryDemoController.java
new file mode 100644
index 00000000..23014c4a
--- /dev/null
+++ b/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/RetryDemoController.java
@@ -0,0 +1,34 @@
+package cn.iocoder.springboot.lab59.resillience4jdemo.controller;
+
+import io.github.resilience4j.retry.annotation.Retry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+@RestController
+@RequestMapping("/retry-demo")
+public class RetryDemoController {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+
+ @Autowired
+ private RestTemplate restTemplate;
+
+ @GetMapping("/get_user")
+ @Retry(name = "backendE", fallbackMethod = "getUserFallback")
+ public String getUser(@RequestParam("id") Integer id) {
+ logger.info("[getUser][准备调用 user-service 获取用户({})详情]", id);
+ return restTemplate.getForEntity("http://127.0.0.1:18080/user/get?id=" + id, String.class).getBody();
+ }
+
+ public String getUserFallback(Integer id, Throwable throwable) {
+ logger.info("[getUserFallback][id({}) exception({})]", id, throwable.getClass().getSimpleName());
+ return "mock:User:" + id;
+ }
+
+}
diff --git a/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/ThreadPoolBulkheadDemoController.java b/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/ThreadPoolBulkheadDemoController.java
new file mode 100644
index 00000000..8f27bb86
--- /dev/null
+++ b/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/ThreadPoolBulkheadDemoController.java
@@ -0,0 +1,49 @@
+package cn.iocoder.springboot.lab59.resillience4jdemo.controller;
+
+import io.github.resilience4j.bulkhead.annotation.Bulkhead;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+@RestController
+@RequestMapping("/thread-pool-bulkhead-demo")
+public class ThreadPoolBulkheadDemoController {
+
+ @Autowired
+ private ThreadPoolBulkheadService threadPoolBulkheadService;
+
+ @GetMapping("/get_user")
+ public String getUser(@RequestParam("id") Integer id) throws ExecutionException, InterruptedException {
+ threadPoolBulkheadService.getUser0(id);
+ return threadPoolBulkheadService.getUser0(id).get();
+ }
+
+ @Service
+ public static class ThreadPoolBulkheadService {
+
+ private Logger logger = LoggerFactory.getLogger(ThreadPoolBulkheadService.class);
+
+ @Bulkhead(name = "backendD", fallbackMethod = "getUserFallback", type = Bulkhead.Type.THREADPOOL)
+ public CompletableFuture getUser0(Integer id) throws InterruptedException {
+ logger.info("[getUser][id({})]", id);
+ Thread.sleep(10 * 1000L); // sleep 10 秒
+ return CompletableFuture.completedFuture("User:" + id);
+ }
+
+ public CompletableFuture getUserFallback(Integer id, Throwable throwable) {
+ logger.info("[getUserFallback][id({}) exception({})]", id, throwable.getClass().getSimpleName());
+ return CompletableFuture.completedFuture("mock:User:" + id);
+ }
+
+ }
+
+
+}
diff --git a/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/TimeLimiterDemoController.java b/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/TimeLimiterDemoController.java
new file mode 100644
index 00000000..5c1f35d4
--- /dev/null
+++ b/lab-59/lab-59-resilience4j-actuator/src/main/java/cn/iocoder/springboot/lab59/resillience4jdemo/controller/TimeLimiterDemoController.java
@@ -0,0 +1,49 @@
+package cn.iocoder.springboot.lab59.resillience4jdemo.controller;
+
+import io.github.resilience4j.bulkhead.annotation.Bulkhead;
+import io.github.resilience4j.timelimiter.annotation.TimeLimiter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+@RestController
+@RequestMapping("/time-limiter-demo")
+public class TimeLimiterDemoController {
+
+ @Autowired
+ private TimeLimiterService timeLimiterService;
+
+ @GetMapping("/get_user")
+ public String getUser(@RequestParam("id") Integer id) throws ExecutionException, InterruptedException {
+ return timeLimiterService.getUser0(id).get();
+ }
+
+ @Service
+ public static class TimeLimiterService {
+
+ private Logger logger = LoggerFactory.getLogger(TimeLimiterService.class);
+
+ @Bulkhead(name = "backendD", type = Bulkhead.Type.THREADPOOL)
+ @TimeLimiter(name = "backendF", fallbackMethod = "getUserFallback")
+ public CompletableFuture getUser0(Integer id) throws InterruptedException {
+ logger.info("[getUser][id({})]", id);
+ Thread.sleep(10 * 1000L); // sleep 10 秒
+ return CompletableFuture.completedFuture("User:" + id);
+ }
+
+ public CompletableFuture getUserFallback(Integer id, Throwable throwable) {
+ logger.info("[getUserFallback][id({}) exception({})]", id, throwable.getClass().getSimpleName());
+ return CompletableFuture.completedFuture("mock:User:" + id);
+ }
+
+ }
+
+}
diff --git a/lab-59/lab-59-resilience4j-actuator/src/main/resources/application.yml b/lab-59/lab-59-resilience4j-actuator/src/main/resources/application.yml
new file mode 100644
index 00000000..d3736cfa
--- /dev/null
+++ b/lab-59/lab-59-resilience4j-actuator/src/main/resources/application.yml
@@ -0,0 +1,66 @@
+resilience4j:
+ # Resilience4j 的断路器配置项,对应 CircuitBreakerProperties 属性类
+ circuitbreaker:
+ instances:
+ backendA:
+ failure-rate-threshold: 50 # 熔断器关闭状态和半开状态使用的同一个失败率阈值,单位:百分比。默认为 50
+ ring-buffer-size-in-closed-state: 5 # 熔断器关闭状态的缓冲区大小,不会限制线程的并发量,在熔断器发生状态转换前所有请求都会调用后端服务。默认为 100
+ ring-buffer-size-in-half-open-state: 5 # 熔断器半开状态的缓冲区大小,会限制线程的并发量。例如,缓冲区为 10 则每次只会允许 10 个请求调用后端服务。默认为 10
+ wait-duration-in-open-state : 5000 # 熔断器从打开状态转变为半开状态等待的时间,单位:微秒
+ automatic-transition-from-open-to-half-open-enabled: true # 如果置为 true,当等待时间结束会自动由打开变为半开;若置为 false,则需要一个请求进入来触发熔断器状态转换。默认为 true
+ register-health-indicator: true # 是否注册到健康监测
+
+ # Resilience4j 的限流器配置项,对应 RateLimiterProperties 属性类
+ ratelimiter:
+ instances:
+ backendB:
+ limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50
+ limit-refresh-period: 10s # 每个周期的时长,单位:微秒。默认为 500
+ timeout-duration: 5s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s
+ register-health-indicator: true # 是否注册到健康监测
+
+ # Resilience4j 的信号量 Bulkhead 配置项,对应 BulkheadConfigurationProperties 属性类
+ bulkhead:
+ instances:
+ backendC:
+ max-concurrent-calls: 1 # 并发调用数。默认为 25
+ max-wait-duration: 5s # 并发调用到达上限时,阻塞等待的时长,单位:微秒。默认为 0
+ # Resilience4j 的线程池 Bulkhead 配置项,对应 ThreadPoolBulkheadProperties 属性类
+ thread-pool-bulkhead:
+ instances:
+ backendD:
+ max-thread-pool-size: 1 # 线程池的最大大小。默认为 Runtime.getRuntime().availableProcessors()
+ core-thread-pool-size: 1 # 线程池的核心大小。默认为 Runtime.getRuntime().availableProcessors() - 1
+ queue-capacity: 200 # 线程池的队列大小。默认为 100
+ keep-alive-duration: 100s # 超过核心大小的线程,空闲存活时间。默认为 20 毫秒
+
+ # Resilience4j 的重试 Retry 配置项,对应 RetryProperties 属性类
+ retry:
+ instances:
+ backendE:
+ max-retry-Attempts: 3 # 最大重试次数。默认为 3
+ wait-duration: 5s # 下次重试的间隔,单位:微秒。默认为 500 毫秒
+ retry-exceptions: # 需要重试的异常列表。默认为空
+ ingore-exceptions: # 需要忽略的异常列表。默认为空
+
+ # Resilience4j 的超时限制器 TimeLimiter 配置项,对应 TimeLimiterProperties 属性类
+ timelimiter:
+ instances:
+ backendF:
+ timeout-duration: 1s # 等待超时时间,单位:微秒。默认为 1 秒
+ cancel-running-future: true # 当等待超时时,是否关闭取消线程。默认为 true
+
+management:
+ endpoints:
+ # Actuator HTTP 配置项,对应 WebEndpointProperties 配置类
+ web:
+ exposure:
+ include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
+ endpoint:
+ # Health 端点配置项,对应 HealthProperties 配置类
+ health:
+ show-details: ALWAYS # 何时显示完整的健康信息。默认为 NEVER 都不展示。可选 WHEN_AUTHORIZED 当经过授权的用户;可选 ALWAYS 总是展示。
+ # 健康检查配置项
+ health:
+ circuitbreakers.enabled: true
+ ratelimiters.enabled: true
diff --git a/lab-59/pom.xml b/lab-59/pom.xml
index b05e21fa..c9b5e486 100644
--- a/lab-59/pom.xml
+++ b/lab-59/pom.xml
@@ -15,6 +15,7 @@
lab-59-user-service
lab-59-resilience4j-demo01
+ lab-59-resilience4j-actuator
diff --git a/pom.xml b/pom.xml
index 42170d7f..0d7279d1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -52,7 +52,7 @@
-
+ lab-42