Skip to content

Commit 6b75d9a

Browse files
author
YunaiV
committed
resilience4j + cloud 示例
1 parent 8fb7122 commit 6b75d9a

File tree

13 files changed

+455
-0
lines changed

13 files changed

+455
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>lab-59</artifactId>
7+
<groupId>cn.iocoder.springboot.labs</groupId>
8+
<version>1.0-SNAPSHOT</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>labx-24-resilience4j-demo01</artifactId>
13+
14+
<properties>
15+
<maven.compiler.target>1.8</maven.compiler.target>
16+
<maven.compiler.source>1.8</maven.compiler.source>
17+
<spring.boot.version>2.2.4.RELEASE</spring.boot.version>
18+
</properties>
19+
20+
<dependencyManagement>
21+
<dependencies>
22+
<dependency>
23+
<groupId>org.springframework.boot</groupId>
24+
<artifactId>spring-boot-starter-parent</artifactId>
25+
<version>${spring.boot.version}</version>
26+
<type>pom</type>
27+
<scope>import</scope>
28+
</dependency>
29+
</dependencies>
30+
</dependencyManagement>
31+
32+
<dependencies>
33+
<!-- 引入 SpringMVC 相关依赖,并实现对其的自动配置 -->
34+
<dependency>
35+
<groupId>org.springframework.boot</groupId>
36+
<artifactId>spring-boot-starter-web</artifactId>
37+
</dependency>
38+
39+
<!-- 引入 Resilience4j Spring Cloud 相关依赖,并实现对其的自动配置 -->
40+
<dependency>
41+
<groupId>io.github.resilience4j</groupId>
42+
<artifactId>resilience4j-spring-cloud2</artifactId>
43+
<version>1.4.0</version>
44+
</dependency>
45+
46+
<!-- 引入 Aspectj 依赖,支持 AOP 相关注解、表达式等等 -->
47+
<dependency>
48+
<groupId>org.aspectj</groupId>
49+
<artifactId>aspectjrt</artifactId>
50+
<version>1.9.5</version>
51+
</dependency>
52+
<dependency>
53+
<groupId>org.aspectj</groupId>
54+
<artifactId>aspectjweaver</artifactId>
55+
<version>1.9.5</version>
56+
</dependency>
57+
58+
</dependencies>
59+
60+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package cn.iocoder.springcloud.labx24.resilience4jdemo;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.context.annotation.Bean;
6+
import org.springframework.web.client.RestTemplate;
7+
8+
@SpringBootApplication
9+
public class DemoApplication {
10+
11+
@Bean
12+
public RestTemplate restTemplate() {
13+
return new RestTemplate();
14+
}
15+
16+
public static void main(String[] args) {
17+
SpringApplication.run(DemoApplication.class, args);
18+
}
19+
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package cn.iocoder.springcloud.labx24.resilience4jdemo.controller;
2+
3+
import io.github.resilience4j.bulkhead.annotation.Bulkhead;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
import org.springframework.web.bind.annotation.GetMapping;
7+
import org.springframework.web.bind.annotation.RequestMapping;
8+
import org.springframework.web.bind.annotation.RequestParam;
9+
import org.springframework.web.bind.annotation.RestController;
10+
11+
@RestController
12+
@RequestMapping("/bulkhead-demo")
13+
public class BulkheadDemoController {
14+
15+
private Logger logger = LoggerFactory.getLogger(getClass());
16+
17+
@GetMapping("/get_user")
18+
@Bulkhead(name = "backendC", fallbackMethod = "getUserFallback", type = Bulkhead.Type.SEMAPHORE)
19+
public String getUser(@RequestParam("id") Integer id) throws InterruptedException {
20+
logger.info("[getUser][id({})]", id);
21+
Thread.sleep(10 * 1000L); // sleep 10 秒
22+
return "User:" + id;
23+
}
24+
25+
public String getUserFallback(Integer id, Throwable throwable) {
26+
logger.info("[getUserFallback][id({}) exception({})]", id, throwable.getClass().getSimpleName());
27+
return "mock:User:" + id;
28+
}
29+
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package cn.iocoder.springcloud.labx24.resilience4jdemo.controller;
2+
3+
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
import org.springframework.beans.factory.annotation.Autowired;
7+
import org.springframework.web.bind.annotation.GetMapping;
8+
import org.springframework.web.bind.annotation.RequestMapping;
9+
import org.springframework.web.bind.annotation.RequestParam;
10+
import org.springframework.web.bind.annotation.RestController;
11+
import org.springframework.web.client.RestTemplate;
12+
13+
@RestController
14+
@RequestMapping("/demo")
15+
public class DemoController {
16+
17+
private Logger logger = LoggerFactory.getLogger(getClass());
18+
19+
@Autowired
20+
private RestTemplate restTemplate;
21+
22+
@GetMapping("/get_user")
23+
@CircuitBreaker(name = "backendA", fallbackMethod = "getUserFallback")
24+
public String getUser(@RequestParam("id") Integer id) {
25+
logger.info("[getUser][准备调用 user-service 获取用户({})详情]", id);
26+
return restTemplate.getForEntity("http://127.0.0.1:18080/user/get?id=" + id, String.class).getBody();
27+
}
28+
29+
public String getUserFallback(Integer id, Throwable throwable) {
30+
logger.info("[getUserFallback][id({}) exception({})]", id, throwable.getClass().getSimpleName());
31+
return "mock:User:" + id;
32+
}
33+
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package cn.iocoder.springcloud.labx24.resilience4jdemo.controller;
2+
3+
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
import org.springframework.web.bind.annotation.GetMapping;
7+
import org.springframework.web.bind.annotation.RequestMapping;
8+
import org.springframework.web.bind.annotation.RequestParam;
9+
import org.springframework.web.bind.annotation.RestController;
10+
11+
@RestController
12+
@RequestMapping("/rate-limiter-demo")
13+
public class RateLimiterDemoController {
14+
15+
private Logger logger = LoggerFactory.getLogger(getClass());
16+
17+
@GetMapping("/get_user")
18+
@RateLimiter(name = "backendB", fallbackMethod = "getUserFallback")
19+
public String getUser(@RequestParam("id") Integer id) {
20+
return "User:" + id;
21+
}
22+
23+
public String getUserFallback(Integer id, Throwable throwable) {
24+
logger.info("[getUserFallback][id({}) exception({})]", id, throwable.getClass().getSimpleName());
25+
return "mock:User:" + id;
26+
}
27+
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package cn.iocoder.springcloud.labx24.resilience4jdemo.controller;
2+
3+
import io.github.resilience4j.retry.annotation.Retry;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
import org.springframework.beans.factory.annotation.Autowired;
7+
import org.springframework.web.bind.annotation.GetMapping;
8+
import org.springframework.web.bind.annotation.RequestMapping;
9+
import org.springframework.web.bind.annotation.RequestParam;
10+
import org.springframework.web.bind.annotation.RestController;
11+
import org.springframework.web.client.RestTemplate;
12+
13+
@RestController
14+
@RequestMapping("/retry-demo")
15+
public class RetryDemoController {
16+
17+
private Logger logger = LoggerFactory.getLogger(getClass());
18+
19+
@Autowired
20+
private RestTemplate restTemplate;
21+
22+
@GetMapping("/get_user")
23+
@Retry(name = "backendE", fallbackMethod = "getUserFallback")
24+
public String getUser(@RequestParam("id") Integer id) {
25+
logger.info("[getUser][准备调用 user-service 获取用户({})详情]", id);
26+
return restTemplate.getForEntity("http://127.0.0.1:18080/user/get?id=" + id, String.class).getBody();
27+
}
28+
29+
public String getUserFallback(Integer id, Throwable throwable) {
30+
logger.info("[getUserFallback][id({}) exception({})]", id, throwable.getClass().getSimpleName());
31+
return "mock:User:" + id;
32+
}
33+
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package cn.iocoder.springcloud.labx24.resilience4jdemo.controller;
2+
3+
import io.github.resilience4j.bulkhead.annotation.Bulkhead;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
import org.springframework.beans.factory.annotation.Autowired;
7+
import org.springframework.stereotype.Service;
8+
import org.springframework.web.bind.annotation.GetMapping;
9+
import org.springframework.web.bind.annotation.RequestMapping;
10+
import org.springframework.web.bind.annotation.RequestParam;
11+
import org.springframework.web.bind.annotation.RestController;
12+
13+
import java.util.concurrent.CompletableFuture;
14+
import java.util.concurrent.ExecutionException;
15+
16+
@RestController
17+
@RequestMapping("/thread-pool-bulkhead-demo")
18+
public class ThreadPoolBulkheadDemoController {
19+
20+
@Autowired
21+
private ThreadPoolBulkheadService threadPoolBulkheadService;
22+
23+
@GetMapping("/get_user")
24+
public String getUser(@RequestParam("id") Integer id) throws ExecutionException, InterruptedException {
25+
threadPoolBulkheadService.getUser0(id);
26+
return threadPoolBulkheadService.getUser0(id).get();
27+
}
28+
29+
@Service
30+
public static class ThreadPoolBulkheadService {
31+
32+
private Logger logger = LoggerFactory.getLogger(ThreadPoolBulkheadService.class);
33+
34+
@Bulkhead(name = "backendD", fallbackMethod = "getUserFallback", type = Bulkhead.Type.THREADPOOL)
35+
public CompletableFuture<String> getUser0(Integer id) throws InterruptedException {
36+
logger.info("[getUser][id({})]", id);
37+
Thread.sleep(10 * 1000L); // sleep 10 秒
38+
return CompletableFuture.completedFuture("User:" + id);
39+
}
40+
41+
public CompletableFuture<String> getUserFallback(Integer id, Throwable throwable) {
42+
logger.info("[getUserFallback][id({}) exception({})]", id, throwable.getClass().getSimpleName());
43+
return CompletableFuture.completedFuture("mock:User:" + id);
44+
}
45+
46+
}
47+
48+
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package cn.iocoder.springcloud.labx24.resilience4jdemo.controller;
2+
3+
import io.github.resilience4j.bulkhead.annotation.Bulkhead;
4+
import io.github.resilience4j.timelimiter.annotation.TimeLimiter;
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
7+
import org.springframework.beans.factory.annotation.Autowired;
8+
import org.springframework.stereotype.Service;
9+
import org.springframework.web.bind.annotation.GetMapping;
10+
import org.springframework.web.bind.annotation.RequestMapping;
11+
import org.springframework.web.bind.annotation.RequestParam;
12+
import org.springframework.web.bind.annotation.RestController;
13+
14+
import java.util.concurrent.CompletableFuture;
15+
import java.util.concurrent.ExecutionException;
16+
17+
@RestController
18+
@RequestMapping("/time-limiter-demo")
19+
public class TimeLimiterDemoController {
20+
21+
@Autowired
22+
private TimeLimiterService timeLimiterService;
23+
24+
@GetMapping("/get_user")
25+
public String getUser(@RequestParam("id") Integer id) throws ExecutionException, InterruptedException {
26+
return timeLimiterService.getUser0(id).get();
27+
}
28+
29+
@Service
30+
public static class TimeLimiterService {
31+
32+
private Logger logger = LoggerFactory.getLogger(TimeLimiterService.class);
33+
34+
@Bulkhead(name = "backendD", type = Bulkhead.Type.THREADPOOL)
35+
@TimeLimiter(name = "backendF", fallbackMethod = "getUserFallback")
36+
public CompletableFuture<String> getUser0(Integer id) throws InterruptedException {
37+
logger.info("[getUser][id({})]", id);
38+
Thread.sleep(10 * 1000L); // sleep 10 秒
39+
return CompletableFuture.completedFuture("User:" + id);
40+
}
41+
42+
public CompletableFuture<String> getUserFallback(Integer id, Throwable throwable) {
43+
logger.info("[getUserFallback][id({}) exception({})]", id, throwable.getClass().getSimpleName());
44+
return CompletableFuture.completedFuture("mock:User:" + id);
45+
}
46+
47+
}
48+
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
resilience4j:
2+
# Resilience4j 的断路器配置项,对应 CircuitBreakerProperties 属性类
3+
circuitbreaker:
4+
instances:
5+
backendA:
6+
failure-rate-threshold: 50 # 熔断器关闭状态和半开状态使用的同一个失败率阈值,单位:百分比。默认为 50
7+
ring-buffer-size-in-closed-state: 5 # 熔断器关闭状态的缓冲区大小,不会限制线程的并发量,在熔断器发生状态转换前所有请求都会调用后端服务。默认为 100
8+
ring-buffer-size-in-half-open-state: 5 # 熔断器半开状态的缓冲区大小,会限制线程的并发量。例如,缓冲区为 10 则每次只会允许 10 个请求调用后端服务。默认为 10
9+
wait-duration-in-open-state : 5000 # 熔断器从打开状态转变为半开状态等待的时间,单位:微秒
10+
automatic-transition-from-open-to-half-open-enabled: true # 如果置为 true,当等待时间结束会自动由打开变为半开;若置为 false,则需要一个请求进入来触发熔断器状态转换。默认为 true
11+
register-health-indicator: true # 是否注册到健康监测
12+
13+
# Resilience4j 的限流器配置项,对应 RateLimiterProperties 属性类
14+
ratelimiter:
15+
instances:
16+
backendB:
17+
limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50
18+
limit-refresh-period: 10s # 每个周期的时长,单位:微秒。默认为 500
19+
timeout-duration: 5s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s
20+
register-health-indicator: true # 是否注册到健康监测
21+
22+
# Resilience4j 的信号量 Bulkhead 配置项,对应 BulkheadConfigurationProperties 属性类
23+
bulkhead:
24+
instances:
25+
backendC:
26+
max-concurrent-calls: 1 # 并发调用数。默认为 25
27+
max-wait-duration: 5s # 并发调用到达上限时,阻塞等待的时长,单位:微秒。默认为 0
28+
# Resilience4j 的线程池 Bulkhead 配置项,对应 ThreadPoolBulkheadProperties 属性类
29+
thread-pool-bulkhead:
30+
instances:
31+
backendD:
32+
max-thread-pool-size: 1 # 线程池的最大大小。默认为 Runtime.getRuntime().availableProcessors()
33+
core-thread-pool-size: 1 # 线程池的核心大小。默认为 Runtime.getRuntime().availableProcessors() - 1
34+
queue-capacity: 200 # 线程池的队列大小。默认为 100
35+
keep-alive-duration: 100s # 超过核心大小的线程,空闲存活时间。默认为 20 毫秒
36+
37+
# Resilience4j 的重试 Retry 配置项,对应 RetryProperties 属性类
38+
retry:
39+
instances:
40+
backendE:
41+
max-retry-Attempts: 3 # 最大重试次数。默认为 3
42+
wait-duration: 5s # 下次重试的间隔,单位:微秒。默认为 500 毫秒
43+
retry-exceptions: # 需要重试的异常列表。默认为空
44+
ingore-exceptions: # 需要忽略的异常列表。默认为空
45+
46+
# Resilience4j 的超时限制器 TimeLimiter 配置项,对应 TimeLimiterProperties 属性类
47+
timelimiter:
48+
instances:
49+
backendF:
50+
timeout-duration: 1s # 等待超时时间,单位:微秒。默认为 1 秒
51+
cancel-running-future: true # 当等待超时时,是否关闭取消线程。默认为 true

0 commit comments

Comments
 (0)