所谓客户端弹性(resiliency),指的是当依赖的服务发生错误或表现不佳时,客户端仍然能够有应对的办法,而不是陷入崩溃或不可用。
本篇将讨论如何通过Hystrix来实现
借助spring cloud,程序员引入Hystrix只需三步
1、首先加入maven依赖
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
2、在启动类中加入@EnableCircuitBreaker
注解
@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
}
3、使用@HystrixCommand
标记一个方法,例如:
@GetMapping("/call")
@HystrixCommand
public String call() {
String url = "http://myservice1/service1";
ResponseEntity responseEntity = restTemplate.getForEntity(url, String.class);
return responseEntity.getBody();
}
@HystrixCommand
并不限于Http调用,它可以用于任何请求资源的方法。当在一个方法上加了这个注解后,Hystrix将会自动生成一个代理类,该代理将包装该方法,并通过专门用于处理远程调用的线程池来管理对该方法的所有调用。当出现以下情况时,熔断器将会生效
超时的默认时间是1秒中。如果上述接口的响应时间是5秒的话,每次请求该接口,熔断器都会在1秒后拒绝继续等待,并返回错误结果。可以通过下面的方式来修改默认的超时时间
@HystrixCommand(
commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000") }
)
从fallback的字面意思来看,是当某个接口不能正常提供服务时的一种备用机制,可以理解为服务降级。例如一个推荐系统,正常情况下我会针对一个用户的具体情况来做推荐,但如果由于对应的接口不能正常提供服务,可以考虑使用别的方式来推荐一些不那么个性化的内容
使用Hystrix来实现的话,就是提供另外一个备用的方法,当熔断器触发后,会自动调用备用方法。下面是一个例子
@GetMapping("/call")
@HystrixCommand(fallbackMethod = "callFallBack")
public String call() {
String url = "http://myservice1/service1";
ResponseEntity responseEntity = restTemplate.getForEntity(url, String.class);
return responseEntity.getBody();
}
public String callFallBack() {
return "fall back result";
}
通过fallbackMethod = "callFallBack"
指定了一个备用方法,备用方法必须与@HystrixCommand
标注的方法拥有相同的参数列表和返回值
当服务依赖的某个外部资源不能很好地工作,有可能会拖垮整个服务本身,为了避免这种事情的发生,可以使用资源隔离的机制。
Hystrix实现隔离的机制是,将某个或某几个熔断器放到指定的线程池中,并限制线程池的资源。
@HystrixCommand(
threadPoolKey = "myThreadPool",
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "30"),
@HystrixProperty(name = "maxQueueSize", value = "10")
}
)
通过threadPoolKey
属性为特定的熔断器设置一个专用的线程池,并通过threadPoolProperties
指定若干个线程池属性,可以对某类外部资源的调用起到隔离的作用。
上图是Hystrix在遇到调用失败后的决策过程
每当Hystrix命令遇到服务错误时,它将开始一个10s(变量1)的计时器,用于检查服务调用失败的频率,如果在10s内的调用总次数达到了20(变量2),并且失败的比例超过了50%(变量3),Hystrix将触发熔断器,让接下来的几乎所有请求都快速失败,但每隔5s(变量4)都会让一个调用去尝试。如果发现某次尝试的Hystrix命令可以正常执行了,就恢复这个熔断器。
以上用括号括起来的4个变量都是可以配置的
设置的方式如下:
@HystrixCommand(
threadPoolKey = "licenseByOrgThreadPool",
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "30"),
@HystrixProperty(name = "maxQueueSize", value = "10")
},
commandProperties ={
@HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value="10"),
@HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value="75"),
@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value="7000"),
@HystrixProperty(name="metrics.rollingStats.timeInMilliseconds",value="15000")
}
)
完整的列表请参考 https://github.com/Netflix/Hystrix/wiki/Configuration
可以使用@DefaultProperties
在class级别配置一些默认的commandProperties,这些属性值将会被应用到当前class下的所有@HystrixCommand
的commandProperties
中,但具体的@HystrixCommand
仍然可以显式地覆盖
@DefaultProperties(
commandProperties ={
@HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value="10")
}
)
public class myClass{
...
}