hystrix是一个容错组件,实现了超时机制和断路器模式。

hystrix提供了熔断降级

降级

降级其实就相当于,当我们向一个服务发起请求,当请求超时了,就会把这次请求记录到服务中,然后就会尝试向其他服务发请求,如果还没成功,就对这次请求进行处理(怎么处理取决于业务需求如)就相当于try catch一样的逻辑,当然hystrix底层使用aop来实现的。

隔离和限流

每当向服务发起一个请求时,就是会发起一个http请求,每一个http请求就要开启一个线程,然后等待服务返回信息,这容易导致线程的堆积,所以就可以用http的URI作为一个标识,然后相同的URI可以开启一个线程池,然后线程池中限定线程数,这样就可以设置拒绝策略,当线程池满了,就可以快速的抛出异常或者拒绝请求,用线程池做到线程隔离来达到限流

熔断

熔断就是有一个阈值,向服务发起请求后,如果不成功,就会记录次数,然后当连续失败次数达到阈值时,下次请求的时候就会直接把这个服务停止。请求有三种状态,可以请求(开),不可请求(关),还有一个中间状态,相当于半开状态,半开状态是什么意思呢,就是可以尝试着去请求,就可以在关闭状态后一段时间,发一个请求尝试一下是否可以请求成功,如果是吧,继续保持关闭状态,如果请求成功,则变成开放状态。

首先Hystrix发生在请求这一端,所以我们先在consumer端引入Hystrix的依赖

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  <version>2.1.1.RELEASE</version>
</dependency>

然后我们来整合一下Hystrix和feign

首先呢,feign有两种方式来指定熔断策略,第一种是直接指定一个类,第二种是用fallbackFactory。区别是一种是可以直接熔断,一种是可以根据不同的类型,进行不同的处理。

首先我们看看第一种,我们可以在@FeignClient注解中加上参数fallback=XXX.class,如下,我们这里的是面向接口编程,可以看我上一篇博客是讲如何用feign的。fallback里面的类也要新建一下。

//这里name是eureka里的服务名
@FeignClient(name = "user-provider",fallback = UserProviderBack.class)
public interface UserAPI extends ProviderApi {

}

新建UserProviderBack类然后实现我们的UserAPI,把所有的方法都实现一遍,这种熔断策略是针对于每个请求资源的接口。每个接口都是同的。注意这个类要加上@Component注解,就是把这个类给到spring容器去管理。

@Component
public class UserProviderBack implements UserAPI {
    @Override
    public String alive() {
        return "降级了!!!!!!!!!!!!!";
    }

    @Override
    public HashMap getMapById(Integer id) {
        return null;
    }
}

最后一步就是要配置properties文件,因为默认Feign在请求发生错误时,是不会用Hystrix做服务降级处理。

feign.hystrix.enabled=true

到这里我们就搞好啦,我们只要服务提供方出错,那么调用方就会去走到fallback类的方法里面,我们可以不启动服务提供方来模拟服务出错。那么降级里面处理就可以按照业务要求,去返回需要的信息,提高系统的可用性。

要注意一些依赖的版本控制,我这里的版本是如下

<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>



<properties>
  <java.version>1.8</java.version>
  <spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties>

还可以用不用fallback,改用fallbackFactory

@FeignClient(name = "user-provider",fallbackFactory = UserProviderBackFactory.class)
public interface UserAPI extends ProviderApi {

}

然后新建UserProviderBackFactory这个类,去实现FallbackFactory接口,这个接口我们可以把我们的接口类型传进去,然后重写create方法,如图,这里的throwable就是具体的异常信息,就可以根据不同的错误类型,进行catch,然后处理。

@Component
public class UserProviderBackFactory implements FallbackFactory<UserAPI> {
    @Override
    public UserAPI create(Throwable throwable) {
        return new UserAPI() {
            @Override
            public String alive() {
               
                return "又又又降级了";
            }

            @Override
            public HashMap getMapById(Integer id) {
                return null;
            }
        };
    }
}

信号量隔离和线程隔离

线程池隔离,用户对服务发起请求后,hystrix会针对每一个不同的服务(用户服务,商品服务等等)来开一个线程池,然后这样就可以针对不同的服务来分配线程数,那么如果线程数太多,就直接抛异常fallback,缺点就是开销比较大。(官方推荐

信号量隔离,用户对服务发起请求后,hystrix会初始化出一个信号量数(可执行的线程数),当一个uri请求时,信号量数减一,当信号量数不够直接fallback。所以就可以针对不同服务,设置不同信号量数,去进行不同服务的隔离,这样做开销就比线程池隔离开销小了。(性能更高)

为什么官方推荐线程池隔离呢?

  1. 线程池可以根据不用服务设置不同的拒绝策略
  2. 线程池可以异步请求
  3. 对于线程池异常的隔离

那我们怎么管理我们的线程数量呢?我们可以引入依赖dashboard和actuator依赖(别忘了配置properties),这些都是请求方去设置的,服务提供方就很轻量级,只负责提供服务。

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
  <version>2.1.1.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

然后在项目入口加上注解@EnableHystrixDashboard,这个注解是actuator包里的,所以要引入actuator依赖

@EnableFeignClients
@SpringBootApplication
@EnableCircuitBreaker
@EnableHystrixDashboard
public class UserConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserConsumerApplication.class, args);
    }

}

然后我们就可以在actuator的服务里访问"/actuator/hystrix.stream",就会一直输出ping,因为是懒加载的,所以要先触发一下服务的请求,我们就先随便请求一下服务里的请求

然后就会输出一下内容,内容有点乱呀,所以我们可以看图形化的东西,请求/hystrix去看这些内容

就会跳转到下面的页面,然后把刚刚的url黏贴进去,这个就会没面请求这个url,然后把里面的数据按照图形化格式展示出来。

那想修改线程池的大小的话可以修改properties配置,默认是10,还有很多配置我就不一一列举了。修改信号量隔离也是在properties配置文件里修改。

以上是我对hystrix基础总结,如果有大佬发现那里不太对,希望可以给我指正,谢谢!!!!!!

 

 

 

 

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐