SpringCloud教程四:Hystrix(断路器)
一、概述
多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”。
对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。
Hystrix音标[hɪst'rɪks],Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
主要功能:服务降级、服务熔断、服务限流、实时监控。
二、原理
当对特定的服务的调用的不可用达到一个阀值(Hystric 是5秒20次) 断路器将会被打开。断路打开后,可用避免连锁故障,fallback方法可以直接返回一个固定值。
三、实践
这个实践代码基于:SpringCloud教程三。
①改造serice-ribbon 工程的代码,首先在pox.xml文件中加入spring-cloud-starter-hystrix的起步依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
在程序的启动类ServiceRibbonApplication 加@EnableHystrix注解开启Hystrix:
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRibbonApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
改造HelloService类,在helloService方法上加上@HystrixCommand注解。该注解对该方法创建了熔断器的功能,并指定了fallbackMethod熔断方法,熔断方法直接返回了一个字符串,字符串为”hello,”+name+”,sorry,error!”,代码如下:
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "helloError")
public String helloService(String name) {
return restTemplate.getForObject("http://SERVICE-HELLO/hello?name="+name,String.class);
}
public String helloError(String name) {
return "hello,"+name+",sorry,error!";
}
}
启动:service-ribbon 工程,当我们访问http://localhost:8764/hello?name=51ma,浏览器显示:
hello 51ma,i am from port:8762
此时关闭 service-hello 工程,当我们再访问http://localhost:8764/hello?name=51ma,浏览器会显示:
hello ,51ma,orry,error!
这就说明当 service-hello 工程不可用的时候,service-ribbon调用 service-hello的API接口时,会执行快速失败,直接返回一组字符串,而不是等待响应超时,这很好的控制了容器的线程阻塞。
②Feign中使用断路器
Feign是自带断路器的,在D版本的Spring Cloud中,它没有默认打开。需要在配置文件中配置打开它,在配置文件加以下代码:
feign:
hystrix:
#开启feign的hystrix支持,默认是false
enabled: true
基于service-feign工程进行改造,只需要在FeignClient的SchedualServicehello接口的注解中加上fallback的指定类就行了:
@FeignClient(value = "service-hello",fallback = SchedualServicehelloHystric.class)
public interface SchedualServicehello {
@RequestMapping(value = "/hello",method = RequestMethod.GET)
String sayhelloFromClientOne(@RequestParam(value = "name") String name);
}
SchedualServicehelloHystric需要实现SchedualServicehello 接口,并注入到Ioc容器中,代码如下:
@Component
public class SchedualServicehelloHystric implements SchedualServicehello {
@Override
public String sayhelloFromClientOne(String name) {
return "sorry "+name;
}
}
启动四servcie-feign工程,浏览器打开http://localhost:8765/hello?name=51ma,注意此时service-hello工程没有启动,网页显示:
sorry 51ma
打开service-hello工程,再次访问,浏览器显示:
hello 51ma,i am from port:8762
这证明断路器起到作用了。
③Hystrix Dashboard (断路器:Hystrix 仪表盘)
基于service-ribbon 改造,Feign的改造和这一样。
首选在pom.xml引入spring-cloud-starter-hystrix-dashboard的起步依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
在主程序启动类中加入@EnableHystrixDashboard注解,开启hystrixDashboard:
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@EnableHystrixDashboard
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRibbonApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
打开浏览器:访问http://localhost:8764/hystrix,界面如下:
点击monitor stream,进入下一个界面,访问:http://localhost:8764/hello?name=51ma
此时会出现监控界面:
四、参考资料
五、源码
加入qq群:Spring全家桶技术交流①群196165973,免费获取源码。