SpringCloud Netflix Hystrix熔断容错降

2020-11-12  本文已影响0人  kaixingdeshui

SpringCloud Netflix Hystrix熔断容错降级

现象
在微服务中,一个请求有可能是多个微服务协同处理,请求一旦大量被阻塞,会占用大量资源,有可能会使整个系统雪崩。
为了防止出现这种现象,需要一种机制来处理请求堆积情况,出现了Hystrix。
Hystrix的构建思路:
1.服务限流:服务消费者限制自身对某一服务能够发起的并发请求数量,超过数量则不调用
2.服务熔断:熔断状态下,服务消费者不会发起对某一服务的调用
3.服务降级:请求异常的情况下,程序执行指定的降级策略

官方文档介绍:
https://www.springcloud.cc/spring-cloud-netflix.html

image.png
Hystrix 集成

1.pom导入依赖

<!--hystrix 熔断容错-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

实现方式一:
继承HystrixCommand,重写run,getFallback方法:

/**
 * hystrix 熔断容错机制
 */
public class CustomerCommand extends HystrixCommand<Object> {

    private RestTemplate restTemplate;

    public CustomerCommand(RestTemplate restTemplate) {
//        super(setter);
        super(//也可以在配置文件里配置信息
                Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("study-hystrix"))
                        .andCommandKey(HystrixCommandKey.Factory.asKey("CustomerController"))
                        //定义线程池
                        .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("studyThreadPool"))
                .andCommandPropertiesDefaults(
                        HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(100)//执行超时时间100ms
                        .withCircuitBreakerSleepWindowInMilliseconds(5000))//熔断时间5s
                .andThreadPoolPropertiesDefaults(
                        HystrixThreadPoolProperties.Setter().withCoreSize(1).withMaxQueueSize(1))

        );
        this.restTemplate = restTemplate;
    }

    @Override
    protected Object run() throws Exception {
        System.out.println("当前线程:"+Thread.currentThread().getName());
        //核心实现,调用方法
        Object result = restTemplate.getForObject("http://hello-server/client_1",String.class,"");
        return result;
    }

    @Override
    protected Object getFallback() {
        System.out.println("降级处理");
        return "返回降级结果";
    }

}

在controller里直接创建调用:

@RestController
public class CustomerController {

  @Autowired
  private RestTemplate restTemplate;

  /**
   *第一种方式实现降级:通过继承HystrixCommand,重写run,getFallback方法
   * @return
   */
  @GetMapping("/test")
  public Object test(){//超时降级处理
      return new CustomerCommand(restTemplate).execute();
  }
}

application配置信息

server:
  port: 8003

spring:
  application:
    name: hystrix-demo
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka

第二种方式:
通过注解的方式

@RestController
public class CustomerController {
    @Autowired
    private RestTemplate restTemplate;
    /**
     * 第二种方式实现降级:用注解的方式
     * 需要在application入口加
     * //熔断注解
     * @EnableCircuitBreaker
     *fallbackMethod :定义降级执行的方法名
     * @return
     */
    @GetMapping("/test2")
    @HystrixCommand(fallbackMethod = "callTimeOutFallBack",
            threadPoolProperties =
            {@HystrixProperty(name = "coreSize",value = "1"),
            @HystrixProperty(name = "queueSizeRejectionThreshold",value = "1")},
            commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "100")})
    public Object getTest2(){//超时降级处理
        return restTemplate.getForObject("http://hello-server/client_1",String.class,"");
    }

    public Object callTimeOutFallBack(){
        return "请求test2 降级";
    }

}

在程序入口加上EnableCircuitBreaker注解

@SpringBootApplication
@EnableEurekaClient
//熔断注解
@EnableCircuitBreaker
public class LearnHystrixApplication {

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

Hystrix资源隔离

不管是注解还是继承HystrixCommand,都是在线程池里执行,确保资源隔离。


image.png

初始化过程

HystrixCommand 的父类 AbstractCommand 构造方法做初始化:


image.png
//命令分组名称(服务名)
this.commandGroup = initGroupKey(group);
//命令名称(接口/业务)
this.commandKey = initCommandKey(key, getClass());
//加载配置
this.properties = initCommandProperties(this.commandKey, propertiesStrategy, commandPropertiesDefaults);
this.threadPoolKey = initThreadPoolKey(threadPoolKey, 
this.commandGroup, this.properties.executionIsolationThreadPoolKeyOverride().get());
//度量器。收集命令执行的数据收集和统计
this.metrics = initMetrics(metrics, this.commandGroup, 
this.threadPoolKey, this.commandKey, this.properties);
//熔断器
this.circuitBreaker = initCircuitBreaker(this.properties.circuitBreakerEnabled().get(), circuitBreaker, this.commandGroup, this.commandKey, this.properties, this.metrics);
//线程池,资源隔离
this.threadPool = initThreadPool(threadPool, this.threadPoolKey, threadPoolPropertiesDefaults);

执行流程

HystrixCommand.execute()返回一个Future对象:

image.png

通过Observable 观察者模式实现发布订阅消费事件


image.png

terminateCommandCleanup
unsubscribeCommandCleanup
applyHystrixSemantics


image.png

度量计数


image.png
线程池执行applyHystrixSemantics--> executeCommandAndObserve->
executeCommandWithSpecifiedIsolation->threadPool.getScheduler
image.png

Hystrix 可视化监控

  1. pom导入依赖
<!--web-->
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
<!--可监视化-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>

2.添加注解

/**
 * 可视化网页
 * http://localhost:9999/hystrix
 */
@SpringBootApplication
//启用hystrix 可视化
@EnableHystrixDashboard
public class LearnDashboardApplication {
    public static void main(String[] args) {
        SpringApplication.run(LearnDashboardApplication.class, args);
    }
}

3.application配置

server:
  port: 9999

spring:
  application:
    name: dashboard-demo

hystrix:
  dashboard:
    proxy-stream-allow-list: "*"
image.png

在需要开放监控的项目中配置监控端点:

#dashboard端点监控
management:
  endpoints:
    web:
      exposure:
        include: "*"
image.png
上一篇下一篇

猜你喜欢

热点阅读