服务容错保护(5、服务熔断)

1. 简介

当请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN),和服务降级很相似,但是服务降级没有熔断策略的设置。

断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒。
在这里插入图片描述

2. 熔断器的三种状态

如同电力过载保护器。它可以实现快速失败,如果它在一段时间内侦测到许多类似的错误,会强迫其以后的多个调用快速失败,不再访问远程服务器,从而防止应用程序不断地尝试执行可能会失败的操作,使得应用程序继续执行而不用等待修正错误,或者浪费CPU时间去等到长时间的超时产生。熔断器也可以使应用程序能够诊断错误是否已经修正,如果已经修正,应用程序会再次尝试调用操作。

熔断器模式就像是那些容易导致错误的操作的一种代理。这种代理能够记录最近调用发生错误的次数,然后决定使用允许操作继续,或者立即返回错误。 熔断器开关相互转换的逻辑如下图:
在这里插入图片描述

  • 当熔断器开关关闭时, 请求被允许通过熔断器. 如果当前健康状况高于设定阈值, 开关继续保持关闭. 如果当前健康状况低于设定阈值, 开关则切换为打开状态
  • 当熔断器开关打开时, 请求被禁止通过
  • 当熔断器开关处于打开状态, 经过一段时间后, 熔断器会自动进入半开状态, 这时熔断器只允许一个请求通过. 当该请求调用成功时, 熔断器恢复到关闭状态. 若该请求失败, 熔断器继续保持打开状态, 接下来的请求被禁止通过

3. 实现

  1. 接consumer01项目,在项目入口添加注解 @EnableCircuitBreaker 启用断路器
  2. 在service中添加服务熔断的测试代码 - 新增方法
	@HystrixCommand(fallbackMethod = "fallBack02", commandProperties = {
		// 默认20个;10s内请求数大于10个时启动熔断
		// 如果错误率没有超过CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE值,不会触发fallBack02()。
		@HystrixProperty(
			name = HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD,
			value = "10"),
		// 默认采样周期为10秒,失败率50%;
		// 这里为了测试,设置请求错误率大于20%时就熔断,当请求符合熔断条件时将触发fallBack02()。
		@HystrixProperty(
			name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE,
			value = "20"),
		// 默认值5000ms;这里设置熔断20秒后去尝试请求
		@HystrixProperty(
			name = HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS,
			value = "20000"),
		// 是否强制开启熔断,默认false;为true时,所有请求都被拒绝,直接到fallback方法
		@HystrixProperty(
			name = HystrixPropertiesManager.CIRCUIT_BREAKER_FORCE_OPEN, value = "false"),
		// 是否强制关闭熔断,默认false;为true时,将忽略错误
		@HystrixProperty(
			name = HystrixPropertiesManager.CIRCUIT_BREAKER_FORCE_CLOSED, value = "false")
	})
	@Override
	public Product getHystrixProduct(Long id) {
		int random = 0;
		try {
			random = SecureRandom.getInstanceStrong().nextInt(10);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		System.out.println("======= random:" + random);
		if(random%2 != 0){
			System.out.println("==== error");
			throw new RuntimeException("我出错了");
		}
		return restTemplate.getForObject("http://PRODUCT-PROVIDER/product/"+id, Product.class);
	}

	public Product fallBack02(Long id) {

		System.out.println("=========fallBack02");
		Product product = new Product();
		product.setId(-1111L);
		product.setNote("系统繁忙稍后再试......");
		return product;
	}

这里需要注意,fallback的犯法入参必须与断路测试的方法入参保持一致,否则会报错

  1. controller层新增测试接口
	@GetMapping("/hystrixproduct/{id}")
	public ResponseEntity<Product> hystrixproduct(@PathVariable Long id){
		Product product = productService.getHystrixProduct(id);
		return ResponseEntity.ok(product);
	}
  1. 测试结果
    给个测试样例:
    在这里插入图片描述
  • postman反复发送post请求,未抛异常时,服务端能正常打印日志
  • 10秒内请求书大于10,并且异常数大于20%时,服务熔断,每次请求都直接进入fallback02
  • 20秒后重试,发现仍然失败则继续保持断开状态,则再等待20秒;发现可以正常请求,则进入初始状态,再次统计10秒内的失败率

4. Feign的服务熔断

  1. 对接口添加注解
@FeignClient(name="product-provider", fallback=FeignEgoProviderImpl.class)

  1. 创建实现类,实现托底方法

详情可在官方进行查阅:
Open-Feign
Hystrix
官方示例:
在这里插入图片描述
在这里插入图片描述


到这里服务熔断就算完成了
实际生产中还需要配置一下Hystrix Dashboard对断路情况进行监控,这个Hystrix仪表盘可能后面也会写一篇文章记录下
后面该继续玩儿容错保护的线程隔离了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值