简单的搭建的流程:第一,eureka注册中心;第二,在eureka上注册的服务;第三,在eureka消费服务的客户端,hystrix,是在客户端上的使用,在调用端嵌入jar包,以jar包的方式使用hystrix,不需要额外的安装,在项目中添加如下依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
@EnableCircuitBreaker或@EnableHystrix开启hystrix的使用,由于这是在服务调用端的添加,因此一般还需要添加@EnableDiscoveryClient注解,还可以使用@SpringCloudApplication,进去这个注解可以发现这个注解包括以下注解,所以@SpringCloudApplication注解可以使用hystrix
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}
hystrix提供5部分的服务,分别是降级、隔离、熔断器、异常和缓存,对于缓存,个人认为是鸡肋的功能,在这里不做说明。在网上看到很多使用代码的方式进行降级等操作,个人认为并不好,这些属于非功能的业务使用注解的方式会更好,因此在这里主要介绍注解的方式。
降级:
/**
* 同步的方式实现
* @return
*/
@HystrixCommand(fallbackMethod = "fallback")
public String consumer() {
return restTemplate.getForObject("http://COMPUTE-SERVICE/add?a=10&b=20", String.class);
}
/**
* 异步的方式实现
* @return
*/
@HystrixCommand(
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value ="40000"),
}
)
public Future<String> consumerA(){
return new AsyncResult<String>() {
@Override
public String invoke() {
return restTemplate.getForObject("http://COMPUTE-SERVICE/add?a=10&b=20", String.class);
}
};
}
public String fallback() {
return "fallbck";
}
有两种实现的方式,一种同步一种异步,当服务调用失败的时候,便会直接调用fallback方法,异步需要调用端按照以下方式处理才能获取相关数据
Future<String> result = consumerService.consumerA();
return result.get();
降级处理的时候可以连续降级,fallback方法是可以继续使用HystrixCommand命令指定降级方法,直到处理完毕
隔离:
/**
* @return
*/
@HystrixCommand(
//表示所属的group,一个group共用线程池,默认使用类名作为一个组,
//同一个分组,使用相同的线程池,线程池的个数按照最小的定义限定,所以线程池定义一次就可以了,再次使用的时候直接定义分组
//同一个分组,不同的线程池,按照不同的线程池来限定
groupKey = "GroupOne",
//线程池的名称
threadPoolKey = "groupOnePoolE",
fallbackMethod = "fallbackTest",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value ="20000"),
},
//以下这些值,在分组的情况下有效
threadPoolProperties = {
//核心线程数
@HystrixProperty(name = "coreSize", value = "3"),
//超过队列的个数会直接失败
@HystrixProperty(name = "maxQueueSize", value = "10"),
//队列小于最大值,拒绝请求
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "3")
//总结:请求数目大于核心线程数+队列的拒绝数的时候就会失败,配置降级方法的时候,不会失败直接调用降级方法
//默认的情况下,以service的名称作为线程池的名称,使用HystrixCommand默认情况下coreSize为10,maxQueueSize使用LinkedBlockingQueue动态拓展,queueSizeRejectionThreshold默认大小值5
}
)
public String consumerPN() {
try{
Thread.sleep(10000);
}catch (Exception e){
}
return restTemplate.getForObject("http://COMPUTE-SERVICE/add?a=10&b=20", String.class);
}
public String fallbackTest(){
return "十次用户请求并发后,超过设置会触发这个降级,否则会出现失败页面";
}
熔断器:
@HystrixCommand(
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value ="11000"),
//是否开启熔断器
@HystrixProperty(name = "circuitBreaker.enabled", value ="true"),
//请求的失败数目超过这个之后,就会打开熔断器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value ="5"),
//熔断器工作时间,默认5秒,超过这个时间便会放流量进去
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value ="50000"),
//出错率超过75%,启动熔断器,默认50%
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value ="75"),
}
)
public String fuse() {
try{
Thread.sleep(10000);
}catch (Exception e){
}
return restTemplate.getForObject("http://COMPUTE-SERVICE/add?a=10&b=20", String.class);
}
异常:
/**
* 以下方式抛出RuntimeException异常的时候不会降级,而是直接按照异常进行处理,将异常抛给调用端
* 如果没有在ignoreExceptions中添加RuntimeException,则会将异常按照降级方法进行处理
* @return
*/
@HystrixCommand(ignoreExceptions = {RuntimeException.class},fallbackMethod = "fallback")
public String consumerAT() {
String result = null;
try {
result = restTemplate.getForObject("http://add?a=10&b=20", String.class);
}catch (Exception e){
throw new RuntimeException();
}
return result;
}