Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
多个微服务之间调用的时候,假设服务A调用服务B和服务C,微服务B和C又调用其他微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,从而引起系统崩溃,这就是所谓的“雪崩效应”。
服务降级是指当服务器压力剧增的情况下,为了预防某些功能(业务场景)出现负荷过载或者响应慢的情况,在其内部暂时舍弃对一些非核心的接口和服务的请求,而直接返回一个提前准备好的 fallback(退路)错误处理信息。这样,虽然提供的是一个有损的服务,但释放了服务器资源以保证核心业务正常运作或高效运作,保证了整个系统的稳定性和可用性。
说白了,就是尽可能的把系统资源让给优先级高的服务。
在微服务架构中,微服务之间的数据交互通过远程调用完成,微服务A调用微服务 B 和微服务 C,微服务B和微服务 C 又调用其它的微服务,此时如果链路上某个微服务的调用响应时间过长或者不可用,那么对微服务 A 的调用就会占用越来越多的系统资源,进而引起系统崩溃,导致“雪崩效应”。
服务熔断是应对雪崩效应的一种微服务链路保护机制。例如在高压电路中,如果某个地方的电压过高,熔断器就会熔断,对电路进行保护。同样,在微服务架构中,熔断机制也是起着类似的作用。当调用链路的某个微服务不可用或者响应时间太长时,会进行服务熔断,不再有该节点微服务的调用,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后,恢复调用链路。
系统规定了多少承受能力,只允许这么些请求能过来,其他的请求不对其进行处理。
服务A调用服务B,如果在A中添加请求缓存,第一次请求后走缓存,不在访问微服务B,即使出现大量请求,不会对B产生高负荷。请求缓存可以使用spring cache实现。
当服务A调用服务B时,设定在5毫秒内所有请求合并到一起,对于服务B的负荷就会减少。使用@HystrixCollapser。方法返回值必须为Future
离分为线程池隔离合信号量隔离。通过判断线程池或信号量是否满,超过容量的请求直接降级,从而达到限流。
org.springframework.cloud spring-cloud-starter-eureka
org.springframework.cloud spring-cloud-starter-hystrix
org.springframework.cloud spring-cloud-starter-ribbon
org.springframework.cloud spring-cloud-starter-feign
server:port: 8083
spring:application:name: hystrix-providereureka:client:service-url:defaultZone: http://localhost:8761/eureka/instance:# 自定义服务名称信息instance-id: hystrix-provider:8083#访问路径可以显示Ip地址prefer-ip-address: true
服务降级就是指服务器忙,请稍候再试,不让客户端等待并立刻返回一个友好提示 fallback。
哪些情况会触发降级:
1)程序运行异常;
2)超时;
3)服务熔断触发服务降级;
4)线程池/信号量打满也会导致服务降级;
@RestController
@RequestMapping("/api")
public class HystrixController {@Value("${server.port}")private String serverPort;@PostMapping("/testProviderHystrix")//一但调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod中的指定方法@HystrixCommand(fallbackMethod = "processHystrixGet",commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "500")})public String testProviderHystrix() throws InterruptedException {System.out.println("testHystrixCommand被调用了");Thread.sleep(1000);return "我是服务端" + serverPort;}public String processHystrixGet() {System.out.println("processHystrixGet被调用了");return serverPort + "服务超时,服务降级啦";}}@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class HystrixProviderApplication {public static void main(String[] args) {SpringApplication.run(HystrixProviderApplication.class, args);}}
在消费端调用接口(继续使用前面使用的eureka-consumer),测试效果
@RestController
@RequestMapping("/api")
public class ConsumerController {@Resourceprivate RestTemplate restTemplate;@PostMapping("/testHystrixCommand")public String testHystrixCommand(){MultiValueMap body = new LinkedMultiValueMap<>();body.add("name", "consumer8090");ResponseEntity responseEntity = restTemplate.postForEntity("http://HYSTRIX-PROVIDER/api/testHystrixCommand", body, String.class);return responseEntity.getBody();}
}
使用前面的搭建好的consumer-feign模块
feign:hystrix:#如果处理自身的容错就开启。enabled: true
@RestController
@RequestMapping("/api")
public class ProviderController implements ConsumerProviderService {@Value("${server.port}")private String serverPort;@Override@PostMapping("/sayHello")public String sayHello(@RequestBody String name) {try {Thread.sleep(1500);} catch (InterruptedException e) {e.printStackTrace();}return "我是服务端" + serverPort + ",你好" + name;}@Override@PostMapping("/getOne")public Person getOne(){return new Person("张三", 22);}
}
@FeignClient(value = "EUREKA-PROVIDER", fallbackFactory = ConsumerProviderServiceBack.class)
public interface ConsumerProviderService {/*** 获取人员信息** @return*/@PostMapping("/api/getOne")Person getOne();@PostMapping("/api/sayHello")String sayHello(@RequestBody String name);
}@Component
public class ConsumerProviderServiceBack implements FallbackFactory {@Overridepublic ConsumerProviderService create(Throwable throwable) {return new ConsumerProviderService() {@Overridepublic Person getOne() {return null;}@Overridepublic String sayHello(String name) {return "服务超时,降级啦";}};}
}//扫描com.xx下的所有包,如果fallback不在同一级或子级包下面需要添加其共同父级包路径
@SpringBootApplication(scanBasePackages = "com.xx")
@EnableEurekaClient
//默认扫描当前注解所在包的同级和子级,若不在同一级或子级,需要申明其Feign客户端所在包路径
@EnableFeignClients(basePackages = "com.xx.springcloudapi")
@EnableCircuitBreaker
public class ConsumerFeignApplication {public static void main(String[] args) {SpringApplication.run(ConsumerFeignApplication.class, args);}}
熔断机制是应对雪崩效应的一种微服务链路保护机制。
当扇出链路的某个微服务出错不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后,恢复调用链路(自我恢复)。
这里我们修改hystrix-provider模块,实现熔断功能
@RestController
@RequestMapping("/api")
public class HystrixController {@Value("${server.port}")private String serverPort;@PostMapping("/testProviderHystrix")//一但调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod中的指定方法@HystrixCommand(fallbackMethod = "processHystrixGet", commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "500"), //超时时间@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),//是否开启断路器@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),//请求次数@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000"),//时间窗口期@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "20")//失败率达到多少跳闸})public String testProviderHystrix() throws InterruptedException {System.out.println("testHystrixCommand被调用了");Thread.sleep(1000);return "我是服务端" + serverPort;}public String processHystrixGet() {System.out.println("processHystrixGet被调用了");return serverPort + "服务超时,服务降级啦";}}
使用Jmeter进行测试:
从结果来看,服务被熔断了,后续不在进入业务代码块,而是直接返回了fallbackMethod的结果
用来控制HystrixCommand.run()的执行
用来控制HystrixCommand.getFallback()的执行
用来控制HystrixCircuitBreaker的行为。
该属性与HystrixCommand和HystrixObservableCommand执行中捕获的指标相关。
涉及HystrixCommand使用HystrixRequestContext的设置。
在微服务架构中为例保证程序的可用性,防止程序出错导致网络阻塞,出现了断路器模型。断路器的状况反应了一个程序的可用性和健壮性,它是一个重要指标。Hystrix Dashboard是作为断路器状态的一个组件,提供了数据监控和友好的图形化界面。
org.springframework.boot spring-boot-starter-actuator
org.springframework.cloud spring-cloud-starter-hystrix-dashboard
启动图形化监控
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {public static void main(String[] args) {SpringApplication.run(HystrixDashboardApplication.class, args);}}
启动hystrix-provider8083,并使用Hystrix Dashboard来进行监控,先请求带有断路器的接口,然后再浏览器访问:http://localhost:8083/hystrix.stream,就会出现如下结果
填入需要监控的服务
右上角对应是图像化的解释