mirror of
https://gitee.com/yudaocode/SpringBoot-Labs.git
synced 2026-09-03 05:53:54 +08:00
resilience4j + 监控 示例
This commit is contained in:
65
lab-59/lab-59-resilience4j-actuator/pom.xml
Normal file
65
lab-59/lab-59-resilience4j-actuator/pom.xml
Normal file
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>lab-59</artifactId>
|
||||
<groupId>cn.iocoder.springboot.labs</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>lab-59-resilience4j-actuator</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<spring.boot.version>2.2.4.RELEASE</spring.boot.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<!-- 引入 SpringMVC 相关依赖,并实现对其的自动配置 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 引入 Resilience4j Starter 相关依赖,并实现对其的自动配置 -->
|
||||
<dependency>
|
||||
<groupId>io.github.resilience4j</groupId>
|
||||
<artifactId>resilience4j-spring-boot2</artifactId>
|
||||
<version>1.4.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 引入 Aspectj 依赖,支持 AOP 相关注解、表达式等等 -->
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<version>1.9.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<version>1.9.5</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 实现对 Actuator 的自动化配置 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<String> getUser0(Integer id) throws InterruptedException {
|
||||
logger.info("[getUser][id({})]", id);
|
||||
Thread.sleep(10 * 1000L); // sleep 10 秒
|
||||
return CompletableFuture.completedFuture("User:" + id);
|
||||
}
|
||||
|
||||
public CompletableFuture<String> getUserFallback(Integer id, Throwable throwable) {
|
||||
logger.info("[getUserFallback][id({}) exception({})]", id, throwable.getClass().getSimpleName());
|
||||
return CompletableFuture.completedFuture("mock:User:" + id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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<String> getUser0(Integer id) throws InterruptedException {
|
||||
logger.info("[getUser][id({})]", id);
|
||||
Thread.sleep(10 * 1000L); // sleep 10 秒
|
||||
return CompletableFuture.completedFuture("User:" + id);
|
||||
}
|
||||
|
||||
public CompletableFuture<String> getUserFallback(Integer id, Throwable throwable) {
|
||||
logger.info("[getUserFallback][id({}) exception({})]", id, throwable.getClass().getSimpleName());
|
||||
return CompletableFuture.completedFuture("mock:User:" + id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -15,6 +15,7 @@
|
||||
<modules>
|
||||
<module>lab-59-user-service</module>
|
||||
<module>lab-59-resilience4j-demo01</module>
|
||||
<module>lab-59-resilience4j-actuator</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
||||
Reference in New Issue
Block a user