histrix简介

熔断器,也叫断路器!(正常情况下 断路器是关的 只有出了问题才打开)用来保护微服务不雪崩的方法。

Hystrix 是 Netflix 公司开源的一个项目,它提供了熔断器功能,能够阻止分布式系统中出现 联动故障。

Hystrix 是通过隔离服务的访问点阻止联动故障的,并提供了故障的解决方案,从 而提高了整个分布式系统的弹性。

当有服务调用的时候,才会出现服务雪崩,所以 Hystrix 常和 OpenFeign,Ribbon 一起出现

快速使用

  • 再消费者中加入histrix依赖
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
  • 修改配置文件
server:
  port: 8094

spring:
  application:
    name: usercar-service
    
eureka:
  client:
    service-url:
      defaultZone: http://XXX.XXX.XXX.XXX:8761/eureka
  instance:
    hostname: localhost
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}

feign:
  hystrix:
    enabled: true	#在springcloud的7版本之前默认是true,之后出现了多种熔断器,默认为false

  • 在feign下新建包histrix,写feign的实现类,并添加组件@component
  • 在feign中的接口中注解@FeignClient添加fallback熟悉 = histrix的实现类

手写熔断器

1.定义状态模型

image-20220722150329416

2.定义注解

image-20220722150353980

3.定于切面类

@Component
@Aspect
public class MyfishAspect {

    //public static final String POINT_CUT = "execute(* com.my.controller.TestController.test(..))";

    public static Map<String, Myfish> fishMap = new HashMap<>();

    private Random random = new Random();

    static {
        fishMap.put("order-service",new Myfish());
    }

    @Around(value = "@annotation(com.my.anno.Myfish)")
    public Object fishAround(ProceedingJoinPoint joinPoint){
        Object result;
        //获取到当前提供者的熔断器
        Myfish myfish = fishMap.get("order-service");
        MyfishStatus status = myfish.getStatus();
        switch (status){
            case OPEN:
                //不能调用
                return "我是熔断器,访问失败,开启熔断器";
            case CLOSE:
                //正常去调用目标方法
                try {
                    result = joinPoint.proceed();
                    return result;
                } catch (Throwable e) {
                    myfish.addFailCount();
                }
            case HALF_OPEN:
                //尝试调用
                int i = random.nextInt(5);
                System.out.println(i);
                if(i == 1){
                    //去调用
                    try {
                        result = joinPoint.proceed();
                        //如果走到这一行,说明成功了
                        myfish.setStatus(MyfishStatus.CLOSE);
                        synchronized (myfish.getLock()){
                            myfish.getLock().notify();
                        }
                        return result;
                    } catch (Throwable e) {
                        return "我是熔断器,访问失败,开启熔断器";
                    }
                }
            default:
                return "我是熔断器,访问失败,开启熔断器";
        }
    }
}

4.定义熔断器

@Data
public class Myfish {

    private MyfishStatus status = MyfishStatus.CLOSE;

    public static final Integer WINDOW_TIME = 20;

    public static final Integer MAX_FAIL_COUNT = 3;

    private AtomicInteger currentFailCount = new AtomicInteger(0);

    private ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
            4,
            8,
            30,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(2000),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy()
    );
    private Object lock = new Object();
    {
        poolExecutor.execute(()->{
            //定期删除
            while(true){
                try {
                    TimeUnit.SECONDS.sleep(WINDOW_TIME);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(this.status.equals(MyfishStatus.CLOSE)){
                    this.currentFailCount.set(0);
                }else {
                    synchronized (lock){
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }


            }
        });
    }

    public void addFailCount() {
        int i = currentFailCount.incrementAndGet();
        if(i >= MAX_FAIL_COUNT){
            this.setStatus(MyfishStatus.OPEN);
            poolExecutor.execute(()->{
                try {
                    TimeUnit.SECONDS.sleep(WINDOW_TIME);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.setStatus(MyfishStatus.HALF_OPEN);
                this.currentFailCount.set(0);
            });
        }

    }
}

hystrix常用配置

feign:
  hystrix:
  enabled: true
hystrix: #hystrix 的全局控制
  command:
    default: #default 是全局控制,也可以换成单个方法控制,把 default 换成方法名即可
      fallback:
        isolation:
          semaphore:
            maxConcurrentRequests: 1000 #信号量隔离级别最大并发数
      circuitBreaker:
        enabled: true #开启断路器
        requestVolumeThreshold: 3 #失败次数(阀值)
        sleepWindowInMilliseconds: 20000 #窗口时间
        errorThresholdPercentage: 60 #失败率
      execution:
        isolation:
          Strategy: thread #隔离方式 thread 线程隔离集合和 SEMAPHORE 信号量隔离
文章作者: 郭远
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 郭远的博客空间
SpringCloud SpringCloud
喜欢就支持一下吧
打赏
微信 微信
支付宝 支付宝