Resilience4j_服务调用端异常熔断

一、背景描述

由于Hystrix官方已经停止更新,Spring 官网推荐使用Resilience4j作为服务的熔断保护中间件,可见Resilience4j的重要性。
为了探究Resilience4j实现服务熔断功能, 我们选用了 consul 作为注册中心,启动了一个服务端(waiter)、一个消费端(consumer)。我们关掉waiter 节点,验证 consumer 节点是否能正常熔断。 consul 启动及运行状态监控,不在这里描述, 我们默认 consul 已经正常运行。
本地安装运行consul 参考:https://jingyan.baidu.com/article/ca41422f732f961eaf99ed5f.html

二、服务端

2.1 pom主要依赖


		1.8
		Greenwich.SR1

	

		
			
				org.springframework.cloud
				spring-cloud-dependencies
				${spring-cloud.version}
				pom
				import
			
		


    	
 			org.springframework.boot
			spring-boot-starter-web
		
		
			org.springframework.boot
			spring-boot-starter-actuator
		
		
		
			org.springframework.cloud
			spring-cloud-starter-consul-discovery
		

2.2 配置文件

application.properties

#0表示服务器随机端口
server.port=0
#consul  地址
spring.cloud.consul.host=localhost
#consul  端口
spring.cloud.consul.port=8500
spring.cloud.consul.discovery.prefer-ip-address=true

bootstrap.properties

#服务名称
spring.application.name=waiter-service

2.3 代码配置

    @PostMapping("/successKey")
    @ResponseBody
    public  String  getSuccessKey(){
        return  "hello wrold!  you have Key !";
    }

    @PostMapping("/pay")
    @ResponseBody
    public  String  pay(){
        return  "OK! you pay  success !";
    }

三、消费方

3.1 pom主要依赖


		1.8
		Greenwich.SR1

	

		
			
				org.springframework.cloud
				spring-cloud-dependencies
				${spring-cloud.version}
				pom
				import
			
		


    	
 			org.springframework.boot
			spring-boot-starter-web
		
		
			org.springframework.boot
			spring-boot-starter-actuator
			
		
			org.springframework.cloud
			spring-cloud-starter-consul-discovery
		
		
			io.github.resilience4j
			resilience4j-spring-boot2
			0.14.1
		

3.2 配置文件

application.properties

server.port=8090

management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

feign.client.config.default.connect-timeout=500
feign.client.config.default.read-timeout=500

spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
spring.cloud.consul.discovery.prefer-ip-address=true
#CircuitBreaker名称为key的熔断配置
resilience4j.circuitbreaker.backends.key.failure-rate-threshold=50
resilience4j.circuitbreaker.backends.key.wait-duration-in-open-state=5000
resilience4j.circuitbreaker.backends.key.ring-buffer-size-in-closed-state=5
resilience4j.circuitbreaker.backends.key.ring-buffer-size-in-half-open-state=3
resilience4j.circuitbreaker.backends.key.event-consumer-buffer-size=10
#CircuitBreaker名称为pay的熔断配置
resilience4j.circuitbreaker.backends.pay.failure-rate-threshold=50
resilience4j.circuitbreaker.backends.pay.wait-duration-in-open-state=5000
resilience4j.circuitbreaker.backends.pay.ring-buffer-size-in-closed-state=5
resilience4j.circuitbreaker.backends.pay.ring-buffer-size-in-half-open-state=3
resilience4j.circuitbreaker.backends.pay.event-consumer-buffer-size=10

bootstrap.properties

#服务名称
spring.application.name=customer-service

3.3 代码配置
1)启动类

@SpringBootApplication
@Slf4j
@EnableDiscoveryClient
@EnableFeignClients
@EnableAspectJAutoProxy
public class CustomerServiceApplication {

	public static void main(String[] args) {
		SpringApplication.run(CustomerServiceApplication.class, args);
	}

	@Bean
	public CloseableHttpClient httpClient() {
		return HttpClients.custom()
				.setConnectionTimeToLive(30, TimeUnit.SECONDS)
				.evictIdleConnections(30, TimeUnit.SECONDS)
				.setMaxConnTotal(200)
				.setMaxConnPerRoute(20)
				.disableAutomaticRetries()
				.setKeepAliveStrategy(new CustomConnectionKeepAliveStrategy())
				.build();
	}
}

2)PayService 用Feign方式调用waiter-server中的接口

@FeignClient(name = "waiter-service", contextId = "pay")
// 如果用了Fallback,不要在接口上加@RequestMapping,path可以用在这里
public interface PayService {
    @PostMapping("/waiter/pay")
    String  pay();

    @PostMapping("/waiter/successKey")
    String  getSuccessKey();

}

3)CustomerController http 入口

@RestController
@RequestMapping("/customer")
@Slf4j
public class CustomerController {

    private CircuitBreaker circuitBreaker;
    @Autowired
    private PayService payService;

    //熔断实现方式一(基于注册熔断器)
    // CustomerController 的构造方法中注入明文“pay”的熔断器
    public CustomerController(CircuitBreakerRegistry registry) {
        circuitBreaker = registry.circuitBreaker("pay");
    }

    //熔断实现方式一(基于注册熔断器)
    //当下游接口异常时候返回“CircuitBreaker effect!!”
    @PostMapping("/pay" )
    public Object pay(){
                return Try.ofSupplier(
                CircuitBreaker.decorateSupplier(circuitBreaker,
                        () -> payService.pay()))
                .recover(CircuitBreakerOpenException.class, "CircuitBreaker effect!!")
                .get();
    }

    //熔断实现方式一(基于注解)
    //声明熔断器名称为“key”的熔断器
    @GetMapping("/key")
    @io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker(name = "key")
    public Object getKey(){
        return payService.getSuccessKey();
     }
 }

四、熔断结果演示

  1. 基于注解未熔断情况
    http://localhost:8090/customer/key
    Resilience4j_服务调用端异常熔断_第1张图片
  2. 基于注册熔断器方式未熔断情况
    http://localhost:8090/customer/pay
    Resilience4j_服务调用端异常熔断_第2张图片
  3. 基于注解熔断情况
    http://localhost:8090/customer/key
    Resilience4j_服务调用端异常熔断_第3张图片
  4. 基于注册熔断器方式熔断情况
    http://localhost:8090/customer/pay
    Resilience4j_服务调用端异常熔断_第4张图片

你可能感兴趣的:(resilience4j)