目录
1 服务雪崩、降级、熔断和限流
1.1 服务雪崩
多个微服务之间调用的时候,假设服务A调用服务B和服务C,服务B和服务C又调用其他的服务,这就是所谓的"扇出"。如果扇出的链路上某个微服务的调用时间相应过长或者不可用,对微服务A的调用就会占用越来越多的资源,进而引起系统崩溃,所谓的“雪崩效应”。
对于高流量的应用来说,单一的后端依赖可能会导致所有的服务器上的资源在几秒钟之内饱和。比失败更糟糕的是,这些应用还有可能导致服务间的延迟增加,备份队列,线程和其他系统资源紧张,导致系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。
所以,通常你发现一个模块儿下某个实例失败后,这个模块儿依然依然会接收流量,然后这个有问题的模块还调用了其他模块儿,这样就会发生级联故障,或者叫雪崩
1.2 服务降级
程序运行异常、超时、线程池打满或服务熔断后,不让客户端等待立刻返回一个友好提示
1.3 服务熔断
服务在某个时间窗口内达到访问失败阈值后会直接拒绝访问,然后调用服务降级方法进行降级
1.4 服务限流
秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行
2 hystrix入门
2.1 初识服务降级
- 1 服务提供方
这里以调用超时为例,服务提供方有一个比较耗时的方法,4000ms执行完
@GetMapping("/timeout")
public String timeout() throws InterruptedException {
Thread.sleep(4000);
return "timeout";
}
- 2 服务方调用
@GetMapping("/payment/fallback")
@HystrixCommand(fallbackMethod = "fallbackMethod")
public String fallback() {
return paymentService.timeout();
}
- 3 编写fallbackMethod方法
public String fallbackMethod() {
return "fallback";
}
- 4 调用方添加EnableCircuitBreaker注解
@EnableEurekaClient
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
// 服务熔断,降级
@EnableCircuitBreaker
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
- 5 配置文件启用hystrix配置
feign:
hystrix:
enabled: true
- 6 调用测试
服务提供者响应时间4000ms,远大于ribbon默认超时时间(1000ms),访问后可以看到fallbackMethod方法进行兜底
2.2 全局降级方法配置
如果不想对每个方法都添加HystrixCommand注解,可以在Controller上添加一个DefaultProperties注解
@RestController
@RequestMapping("/consumer")
@DefaultProperties(defaultFallback = "fallbackMethod")
public class PaymentController {
这个时候去掉方法上的HystrixCommand的fallback属性进行测试,可以看到同样的效果
@GetMapping("/payment/fallback")
@HystrixCommand
public String fallback() {
return paymentService.timeout();
}
如果同时存在DefaultProperties注解和HystrixCommand的fallback属性会怎样?
@GetMapping("/payment/fallback")
@HystrixCommand(fallbackMethod = "fallbackMethod2")
public String fallback() {
return paymentService.timeout();
}
public String fallbackMethod2() {
return "fallback2";
}
测试
可以看到方法注解自定义的fallback方法生效。这里可以得出结论方法注解配置的fallback方法优先级高于类级别的fallback优先级
2.3 基于FeignClient配置的降级处理
- 1 创建一个PaymentService接口实现类
@Component
public class PaymentServiceFallback implements PaymentService {
@Override
public Map getPayment(Long id) {
Map<String, String> map = new HashMap<>();
map.put("fallback", "fallback");
return map;
}
@Override
public String timeout() {
return "timeout fallback";
}
}
- 2 PaymentService配置fallback
@Component
@FeignClient(value = "PAYMENT", fallback = PaymentServiceFallback.class)
public interface PaymentService {
@GetMapping("/payment/get")
Map getPayment(@RequestParam("id") Long id);
@GetMapping("/payment/timeout")
String timeout();
}
- 3 去掉前面配置的方法上的HystrixCommand注解和类上的DefaultProperties注解,进行测试
- 4 优先级说明
FeignClient配置的降级方法优先级低于DefaultProperties配置的降级方法,感兴趣的读着可以自己测试
2.4 服务熔断
2.4.1 熔断测试
测试代码
@GetMapping("/payment/circuit-breaker/{id}")
@HystrixCommand
public String generateFlow(@PathVariable("id") Long id) {
if (id < 0) {
throw new RuntimeException("id 不能为负数");
}
return UUID.randomUUID().toString();
}
这里作如下操作:
先频繁访问:http://localhost:8089/consumer/payment/circuit-breaker/-1
然后访问:http://localhost:8089/consumer/payment/circuit-breaker/1,发现仍然进入fallback方法
2.4.2 相关配置
3 hystrix常用的属性
3.1 超时时间配置
3.1.1 ribbon超时配置
本案例中用的是feign进行调用,所以首先要保证ribbon层级可以调通,这里配置ribbon超时时间5s
ribbon:
ReadTimeout: 5000 # 建立连接时间
ConnectTimeout: 5000 # 建立连接后读取资源用的时间
3.1.2 hystrix默认超时时间
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000
配置好之后进行测试,发现可以调通
3.1.3 基于方法的超时时间
execution.isolation.thread.timeoutInMilliseconds
@GetMapping("/payment/self-fallback")
@HystrixCommand(fallbackMethod = "fallbackMethod", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
public String selfFallback() {
return paymentService.timeout();
}
如果希望某个方法hystrix超时时间小一些可以通过这个方式配置,访问测试
说明:如果execution.isolation.thread.timeoutInMilliseconds和默认配置一起配置,则取超时时间较小的那个配置