Hystrix 具备服务降级、服务容错、服务熔断、线程和信号隔离、请求缓存、请求合并以及服务监控等强大功能。
多层服务调用中,较低级别的服务中的服务故障可能导致用户级联故障。当对特定服务的呼叫达到一定阈值时(Hystrix中的默认值为5秒内的20次故障),电路打开,不进行通话。在错误和开路的情况下,开发人员可以提供后备。
下图来自官方网站
文章图片
Hystrix特性
1.请求熔断: 当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN).这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN).
2.服务降级:Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存.告知后面的请求服务不可用了,不要再来了。
3.依赖隔离(采用舱壁模式,Docker就是舱壁模式的一种):在Hystrix中, 主要通过线程池来实现资源隔离. 通常在使用的时候我们会根据调用的远程服务划分出多个线程池.比如说,一个服务调用两外两个服务,你如果调用两个服务都用一个线程池,那么如果一个服务卡在哪里,资源没被释放。后面的请求又来了,导致后面的请求都卡在哪里等待,导致你依赖的A服务把你卡在哪里,耗尽了资源,也导致了你另外一个B服务也不可用了。这时如果依赖隔离,某一个服务调用A B两个服务,如果这时我有100个线程可用,我给A服务分配50个,给B服务分配50个,这样就算A服务挂了,我的B服务依然可以用。
4.请求缓存:比如一个请求过来请求用户的数据,你后面的请求也过来请求同一个用户的数据,这时我不会继续走原来的那条请求链路了,而是把第一次请求缓存过了,把第一次的请求结果返回给后面的请求。
5.请求合并:我依赖于某一个服务,我要调用N次,比如说查数据库的时候,我发了N条请求发了N条SQL然后拿到一堆结果,这时候我们可以把多个请求合并成一个请求,发送一个查询多条数据的SQL的请求,这样我们只需查询一次数据库,提升了效率。
我们前面EurekaDiscovery2实例中,使用了Feign来调用EurekaDiscovery中的接口,Feign内部已包含了hystrix。下面我们先使用Feign来实现降级融断。
在EurekaDiscovery2配置中添加
feign:
hystrix:
enabled: true# 开启hystrix
我们添加一个Fallback类并实现HelloRemote接口
@Component
public class HelloFallback implements HelloRemote {
@Override
public String home(@RequestParam("name") String name) {
return name+"现在太拥挤了, 请稍后重试~-Feign";
}
}
我们指定fallback类为HelloFallback
@FeignClient(name= "eurekadiscovery", fallback = HelloFallback.class)
public interface HelloRemote {
@GetMapping("/hi")
public String home(@RequestParam("name") String name);
}
下面我们启动实例来验证一下
正常调用:
文章图片
我们模拟EurekaDiscovery挂掉(关闭),触发了服务降级
文章图片
超时导致服务降级,默认feign调用超时是1000毫秒,我们EurekaDiscovery中将线程sleep1000豪秒,同样出现了上面一样的服务降级。
我们可以通下面的配置来设置超时时间
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
通过调整hystrix的超时时间,服务能正常调用
文章图片
当我们没有使用Feign时也可直接引用Hystrix组件来实现在,我们在项目中引入spring-cloud-starter-netflix-hystrix
启动类中我们添加注解@EnableCircuitBreaker 允许断路器
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class EurekaDiscovery2Application { @Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
} public static void main(String[] args) {
SpringApplication.run(EurekaDiscovery2Application.class, args);
}}
我们通过@HystrixCommand
@HystrixCommand(fallbackMethod = "fallback")
public String home(@RequestParam("name") String name)
{
return restTemplate.getForEntity("http://EUREKADISCOVERY/hi?name="+name,String.class).getBody();
}public String fallback(String name) {
return name+",现在太拥挤了, 请稍后重试~";
}
我们启动实例,能正常调用
文章图片
我们模拟EurekaDiscovery挂掉(关闭),触发了服务降级
【SpringCloud浅尝(八)——Hystrix】
文章图片
我们还可以通过@DefaultProperties(defaultFallback = "defaultFallback"),来指定默认的FallBack函数,这样就不需要每个 @HystrixCommand 注解都指定一个FallBack函数了
@RestController
@DefaultProperties(defaultFallback = "defaultFallback")
public class HelloController {
@Autowired
privateRestTemplate restTemplate;
@GetMapping("/hi")
@HystrixCommand
// @HystrixCommand(fallbackMethod = "fallback")
public String home(@RequestParam("name") String name)
{
return restTemplate.getForEntity("http://EUREKADISCOVERY/hi?name="+name,String.class).getBody();
}public String fallback(String name) {
return name+",现在太拥挤了, 请稍后重试~";
}public String defaultFallback()
{
return "现在太拥挤了, 请稍后重试~";
}
这样我们降级后就会调用默认的FallBack函数
文章图片
我们还可以通过@HystrixCommand来设定超时时间,我们一般都是采用在配置文件中设置超时间时间。
@HystrixCommand(commandProperties = {
// 设置超时时间为3秒
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "https://www.it610.com/article/3000")
})
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
home:
execution:
isolation:
thread:
timeoutInMilliseconds: 1000
推荐阅读
- SpringCloud浅尝(六)——Bus
- SpringCloud浅尝(三)——Eureka
- SpringCloud浅尝(十)——Sleuth ZipKin
- SpringCloud浅尝(九)——Hystrix Dashboard
- SpringCloud(三)多节点高可用Eureka注册中心集群
- springcloud搭建eureka服务
- SpringCloud之 Eureka 的服务治理
- 搭建微服务(服务提供者与服务消费者)
- springcloud 服务调用成功几次之后都会失败