一、Resilience4j 实现断路器
创建SpringBoot 项目 resilience4j-circuitbreaker-demo
1.1 依赖
<dependency><groupId>io.github.resilience4j</groupId><artifactId>resilience4j-spring-boot2</artifactId><version>0.14.1</version></dependency>
1.2 配置
resilience4j:circuitbreaker: #断路器backends:menu: #menu 熔断器event-consumer-buffer-size: 10failure-rate-threshold: 50ring-buffer-size-in-closed-state: 5ring-buffer-size-in-half-open-state: 3wait-duration-in-open-state: 5000order: #order 熔断器event-consumer-buffer-size: 10failure-rate-threshold: 50ring-buffer-size-in-closed-state: 5ring-buffer-size-in-half-open-state: 3wait-duration-in-open-state: 5000
1.3 注册和处理熔断
@RestController@RequestMapping("/customer")@Slf4jpublic class CustomerController {@Autowiredprivate CoffeeService coffeeService;@Autowiredprivate CoffeeOrderService coffeeOrderService;private CircuitBreaker circuitBreaker;/*** 代码方式* 注册 "menu" 断路器* 注册 "menu" 限流器*/public CustomerController(CircuitBreakerRegistry circuitBreakerRegistry) {circuitBreaker = circuitBreakerRegistry.circuitBreaker("menu");}@GetMapping("/getCoffeeMenu")public List<String> getCoffeeMenu() {return Try.ofSupplier(CircuitBreaker.decorateSupplier(circuitBreaker,() -> coffeeService.coffee())).recover(CircuitBreakerOpenException.class, Collections.emptyList()) //熔断处理.get(); //返回结果}/*** @return* @io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker 注解方式断路器 order*/@PostMapping("order")@io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker(name = "order")public Map<String, Object> createOrder() {Map<String, Object> stringObjectMap = new HashMap<>();stringObjectMap.put("name", "布卡");log.info("Order {}", stringObjectMap);return coffeeOrderService.coffeeOrder(stringObjectMap);}}
1.4 测试
- docker 启动 consul 服务注册中心
- 启动项目 consul-waiter-service
- 启动项目 resilience4j-circuitbreaker-demo
```shell
执行
curl -X GET http://localhost:8011/customer/getCoffeeMenu返回
[“38029 “,”ESPRESSO COFFEES $12”,”HANDMADE COFFEES $15”,”SOOTHING HOT ALTERNATIVES $20”,”COLD ALTERNATIVES $8”]
关闭consul-waiter-service项目
快速执行多次
curl -X GET http://localhost:8011/customer/getCoffeeMenu
返回[],熔断生效
<a name="KGaAi"></a>## 二、Resilience4j 实现限流<a name="bulkhead"></a>### 2.1 bulkhead复制项目resilience4j-circuitbreaker-demo 修改为 bulkhead-customer-service<a name="09cd0eaf"></a>#### 2.1.1 配置```yamlresilience4j:circuitbreaker: #断路器backends:menu: #menu 熔断器event-consumer-buffer-size: 10failure-rate-threshold: 50ring-buffer-size-in-closed-state: 5ring-buffer-size-in-half-open-state: 3wait-duration-in-open-state: 5000order: #order 熔断器event-consumer-buffer-size: 10failure-rate-threshold: 50ring-buffer-size-in-closed-state: 5ring-buffer-size-in-half-open-state: 3wait-duration-in-open-state: 5000#限流控制bulkhead:backends:menu:max-concurrent-call: 5 #最多5个线程max-wait-time: 5 #最多等待5sorder:max-concurrent-call: 1max-wait-time: 5
2.1.2 注册和限制
@RestController@RequestMapping("/customer")@Slf4jpublic class CustomerController {@Autowiredprivate CoffeeService coffeeService;@Autowiredprivate CoffeeOrderService coffeeOrderService;private CircuitBreaker circuitBreaker;private Bulkhead bulkhead;/*** 代码方式* 注册 "menu" 断路器* 注册 "menu" 限流器*/public CustomerController(CircuitBreakerRegistry circuitBreakerRegistry,BulkheadRegistry bulkheadRegistry) {circuitBreaker = circuitBreakerRegistry.circuitBreaker("menu");bulkhead = bulkheadRegistry.bulkhead("menu");}@GetMapping("/getCoffeeMenu")public List<String> getCoffeeMenu() {return Try.ofSupplier(Bulkhead.decorateSupplier(bulkhead,CircuitBreaker.decorateSupplier(circuitBreaker,() -> coffeeService.coffee()))).recover(CircuitBreakerOpenException.class, Collections.emptyList()) //熔断处理.recover(BulkheadFullException.class, Collections.emptyList()).get(); //返回结果}/*** @return* @io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker 注解方式断路器 order* @io.github.resilience4j.bulkhead.annotation.Bulkhead 注解方式限流 order*/@PostMapping("order")@io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker(name = "order")@io.github.resilience4j.bulkhead.annotation.Bulkhead(name = "order")public Map<String, Object> createOrder() {Map<String, Object> stringObjectMap = new HashMap<>();stringObjectMap.put("name", "布卡");log.info("Order {}", stringObjectMap);return coffeeOrderService.coffeeOrder(stringObjectMap);}}
2.1.3 测试
- docker 启动 consul 服务注册中心
- 启动项目 consul-waiter-service
- 启动项目 bulkhead-customer-service
- 安装 ab 性能测试工具 ```shell sudo apt-get update sudo apt-get install apache2-utils
测试
-n 总的请求数 -c 一次同时并发的请求数 ab -n 10 -c 5 http://localhost:8011/customer/getCoffeeMenu
- 输出结果- 加大并发(结果有13个失败)```shellab -n 20 -c 10 http://localhost:8011/customer/getCoffeeMenu

2.2 RateLimiter
创建项目 ratelimiter-waiter-service
2.2.1 配置
resilience4j:ratelimiter:limiters:coffee:limit-for-period: 5 #限制5次limit-refresh-period-in-millis: 30000 #30秒register-health-indicator: truesubscribe-for-events: truetimeout-in-millis: 5000 #5秒超时order:limit-for-period: 3limit-refresh-period-in-millis: 30000register-health-indicator: truesubscribe-for-events: truetimeout-in-millis: 1000
2.2.2 注册RateLimiter
@Slf4j@RestControllerpublic class WaiterController {private RateLimiter rateLimiter;public WaiterController(RateLimiterRegistry rateLimiterRegistry) {//非注解方式,注册限流器rateLimiter = rateLimiterRegistry.rateLimiter("coffee");}/*** @param request* @return*/@GetMapping(value = "/coffee", produces = "application/json")public List<String> coffeeMenu(HttpServletRequest request) {List<String> result = null;try {result = rateLimiter.executeSupplier(() -> Arrays.asList(request.getServerPort() + " ", "ESPRESSO COFFEES $12", "HANDMADE COFFEES $15", "SOOTHING HOT ALTERNATIVES $20", "COLD ALTERNATIVES $8"));log.info("Get Order: {}", result);} catch (RequestNotPermitted e) {log.warn("Request Not Permitted! {}", e.getMessage(), e);}return result;}/*** 注解方式限流** @param params* @return*/@io.github.resilience4j.ratelimiter.annotation.RateLimiter(name = "order")@PostMapping(value = "/order", consumes = "application/json")public Map<String, Object> coffeeMenu(@RequestBody Map<String, Object> params) {log.info("order coffee");params.put("status", "success");params.put("payMoney", "$19");return params;}}
2.2.3 测试
- 本地docker 启动consul 服务注册中心
- 启动项目 bulkhead-customer-service
- 启动项目 ratelimiter-waiter-service
访问 http://localhost:8011/customer/getCoffeeMenu ,接口限制30秒内访问5次
项目地址
https://github.com/h-dj/SpringCloud-Learning
