admin管理员组

文章数量:1597415

前言

Hystrix,[hɪst’rɪks]

Hystrix 是一个延迟和容错库,旨在隔离远程系统、服务和第三方库,阻止级联故障,在复杂的分布式系统中实现恢复能力。

Hystrix is a latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable.

Hystrix的设计目标

1、通过客户端库对延迟和故障进行保护和控制。

2、在一个复杂的分布式系统中停止级联故障。

3、快速失败和快速恢复。

4、在合理的情况下回退和优雅降级。

5、开启近实时监控、告警和操作控制。

Hystrix的降级策略

Hystrix提供了如下三种降级策略:Hystrix参数说明

  • 熔断降级

    默认在10秒内,发送20次请求,失败率达到50%,就会触发熔断降级。

  • 超时降级

    默认请求的响应时间超过1秒,就会触发超时降级。

  • 资源隔离降级

    资源隔离分为信号量隔离和线程池隔离。

    • 信号量隔离

      调用线程与hystrixCommand线程是同一个线程。同步方式。资源消耗小。不支持超时。

    • 线程池隔离

      调用线程与hystrixCommand线程不是同一个线程。异步方式。支持超时。可以为每个服务单独分配线程池。大量线程的上下文切换带来的开销比较大。

Hystrix全局配置

@HystrixCommand注解的配置优先于Hystrix全局配置

hystrix:
    command:
        default:
            circuitBreaker:
                enabled: true
                requestVolumeThreshold: 20
                errorThresholdPercentage: 50
                sleepWindowInMilliseconds: 5000
            execution:
                timeout:
                    enabled: true
                isolation:
                    thread:
                        timeoutInMilliseconds: 2000
                        interruptOnTimeout: true
                    semaphore:
                        maxConcurrentRequests: 10
                    strategy: THREAD
            metrics:
                rollingStats:
                    timeInMilliseconds: 10000
    threadpool:
        default:
            coreSize: 10
            maximumSize: 19
            allowMaximumSizeToDivergeFromCoreSize: false
            keepAliveTimeMinutes: 1
            maxQueueSize: -1
            queueSizeRejectionThreshold: 5

代码演示1、Hystrix

1、 首先在 pom.xml 中导入如下依赖:

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

2、启动类添加 @EnableCircuitBreaker 注解或者 @EnableHystrix 注解

@SpringBootApplication
@EnableCircuitBreaker
public class HystrixSpringApplication {
  
  public static void main(String[] args) {
    SpringApplication.run(HystrixSpringApplication.class, args);
  }
}

3、准备HystrixService以及实现类HystrixServiceImpl

HystrixService

public interface HystrixService {

    String hystrixMethod(String name);
}

HystrixServiceImpl

@Service
public class HystrixServiceImpl implements HystrixService {

    @Autowired
    private RestTemplate restTemplate;

    @Override
    public String hystrixMethod(String name) {
        return restTemplate.getForObject("http://localhost:8081/order/orders", String.class);
    }

}

4.1、熔断触发降级演示

HystrixController

@RestController
@RequestMapping("hystrix")
public class HystrixController {

    @Autowired
    private HystrixService hystrixService;

    @GetMapping("{num}")
    @HystrixCommand(fallbackMethod = "circuitBreakerFallback", commandProperties = {
            @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ENABLED, value = "true"),
            @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, value = "20"),
            @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, value = "50"),
            @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value = "5000"),
            @HystrixProperty(name = HystrixPropertiesManager.METRICS_ROLLING_STATS_TIME_IN_MILLISECONDS, value = "10000")
    })
    public String testCircuitBreaker(@PathVariable Integer num, @RequestParam String name) {
        if (num % 2 == 0) {
            return "请求成功";
        }
        return hystrixService.hystrixMethod(name);
    }

  	// fallback方法的参数个数、参数类型、返回值类型要与原方法对应,fallback方法的参数多加个Throwable
    public String circuitBreakerFallback(Integer num, String name) {
        return "请求失败,请稍后重试";
    }

}

circuitBreaker.enabled:是否开启断路器,默认true

circuitBreaker.requestVolumeThreshold:请求数量的阈值,默认20

circuitBreaker.errorThresholdPercentage:失败的比例阈值,默认50

circuitBreaker.sleepWindowInMilliseconds:熔断的时长,默认5000

metrics.rollingStats.timeInMilliseconds:统计的时间窗口的时间段大小,默认10000

实际结果:不启动order服务对应的应用的情况下,先请求 http://localhost:8080/hystrix/2?name=tom,得到的是“请求成功”;接着请求 http://localhost:8080/hystrix/1?name=tom,得到的是“请求失败,请稍后重试”,当触发熔断时,这时请求 http://localhost:8080/hystrix/2?name=tom,得到的却是“请求失败,请稍后重试”,过了熔断的时长5秒后,再次请求 http://localhost:8080/hystrix/2?name=tom,发现得到的是“请求成功”。

4.2、超时触发降级演示

@RestController
@RequestMapping("hystrix")
public class HystrixController {

    @Autowired
    private HystrixService hystrixService;

    @GetMapping
    @HystrixCommand(fallbackMethod = "timeoutFallback", commandProperties = {
            @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_TIMEOUT_ENABLED, value = "true"),
            @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS, value = "10000"),
            @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_THREAD_INTERRUPT_ON_TIMEOUT, value = "true")
    })
    public String testTimeout(@RequestParam String name) {
        return hystrixService.hystrixMethod(name);
    }

    public String timeoutFallback(String name) {
        return "请求超时,请稍后重试";
    }
}

execution.timeout.enabled:是否开启请求超时,默认true

execution.isolation.thread.timeoutInMilliseconds:请求的超时时间,默认10000

execution.isolation.thread.interruptOnTimeout:当请求超时时,是否中断线程,默认true

启动Order应用

@RestController
public class OrderServiceImpl implements OrderService {

    @Value("${server.port}")
    private Integer port;

    @Override
    public String orders() {
        try {
          	// 设置睡眠2秒
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return String.valueOf(port);
    }
}

实际结果:请求 http://localhost:8080/hystrix?name=tom ,得到的是“请求超时,请稍后重试”。如果去掉Order应用的睡眠2秒的代码,则得到的是“8081”,即Order应用对应的服务返回的结果。

4.3、资源隔离(线程池)触发降级

@RestController
@RequestMapping("hystrix")
public class HystrixController {

    @Autowired
    private HystrixService hystrixService;

    @GetMapping("isolation/threadpool")
    @HystrixCommand(fallbackMethod = "isolationFallback",
            commandProperties = {
               		@HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY, value = "THREAD")
            },
            threadPoolProperties = {
                    @HystrixProperty(name = HystrixPropertiesManager.CORE_SIZE, value = "10"),
                    @HystrixProperty(name = HystrixPropertiesManager.MAX_QUEUE_SIZE, value = "-1"),
                    @HystrixProperty(name = HystrixPropertiesManager.QUEUE_SIZE_REJECTION_THRESHOLD, value = "2"),
                    @HystrixProperty(name = HystrixPropertiesManager.KEEP_ALIVE_TIME_MINUTES, value = "1"),
            }
    )
    public String testThreadPoolIsolation(@RequestParam String name) {
        return hystrixService.hystrixMethod(name);
    }

    public String isolationFallback(String name) {
        return "资源隔离拒绝,请稍后重试";
    }
}

execution.isolation.strategy:资源隔离策略,支持THREAD、SEMAPHORE。默认THREAD

coreSize:线程池的核心线程数,默认10

maximumSize:线程池的最大线程数,默认10(实际在操作中无法识别该属性,待后期版本验证)

allowMaximumSizeToDivergeFromCoreSize:是否使maximumSize参数生效,默认false(实际在操作中无法识别该属性,待后期版本验证)

maxQueueSize:默认-1(如果是-1,则线程池的内部的队列使用SynchronousQueue,否则使用LinkedBlockingQueue)

keepAliveTimeMinutes:线程池中的线程的生存时间(单位:分钟),默认1

queueSizeRejectionThreshold:线程池中的队列长度达到多少就可以拒绝添加任务,即使队列长度没有达到 maxQueueSize。因为阻塞队列的maxQueueSize不能动态调整,所以引用这个参数来动态调整拒绝任务时的队列长度。默认5。

启动Order应用

@RestController
public class OrderServiceImpl implements OrderService {

    @Value("${server.port}")
    private Integer port;

    @Override
    public String orders() {
        try {
          	// 设置睡眠2秒
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return String.valueOf(port);
    }
}

4.4、资源隔离(信号量)触发降级

@RestController
@RequestMapping("hystrix")
public class HystrixController {

    @Autowired
    private HystrixService hystrixService;

    @GetMapping("isolation/semaphore")
    @HystrixCommand(fallbackMethod = "isolationFallback",
            commandProperties = {
                    @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY, value = "SEMAPHORE"),
                    @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS, value = "2")
            }
    )
    public String testSemaphoreIsolation(@RequestParam String name) {
        return hystrixService.hystrixMethod(name);
    }

    public String isolationFallback(String name) {
        return "资源隔离拒绝,请稍后重试";
    }
}

execution.isolation.strategy:资源隔离策略,支持THREAD、SEMAPHORE。默认THREAD

execution.isolation.semaphore.maxConcurrentRequests:信号量隔离中的最大并发请求数,默认10

启动Order应用

@RestController
public class OrderServiceImpl implements OrderService {

    @Value("${server.port}")
    private Integer port;

    @Override
    public String orders() {
        try {
          	// 设置睡眠2秒
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return String.valueOf(port);
    }
}

代码演示2、Hystrix+Open Feign

在服务提供方定义 feign client 接口 以及 fallback,在服务消费方定义具体的降级策略。

一、Order服务

OrderService

@RequestMapping("order")
public interface OrderService {
  
  @GetMapping("orders")
  String orders();
}

OrderServiceImpl

@RestController
public class OrderServiceImpl implements OrderService {
  
  @Value("${server.port}")
  private Integer port;
  
  @Override
  public String orders() {
    try {
      Thread.sleep(2000);
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt():
    }
    return String.valueOf(port);
  }
}

OrderServiceFeignClient

@FeignClient(value = "spring-cloud-order", fallback = OrderServiceFallback.class)
public interface OrderServiceFeignClient extends OrderService {
  
}

OrderServiceFallback

public class OrderServiceFallback implements OrderServiceFeignClient {
  
  @GetMapping("orders")
  @Override
  public String orders() {
    return "系统繁忙,请稍后重试";
  }
}

二、User服务

UserController

@RestController
@RequestMapping("user")
public class UserController {
  
  @Resource
  private OrderServiceFeignClient orderServiceFeignClient;
  
  @GetMapping("orders")
  pubic String orders() {
    return orderServiceFeignClient.orders();
  }
}

SpringCloudUserApplication

@SpringBootApplication(scanBasePackages = {
  "com.mzs.springcloud.user"
  "com.mzs.order.api.fallback"	// order服务fallback的包路径
})
@EnableFeignClients(basePackages = {
  "com.mzs.order.api.clients"		// order服务feign client的包路径
})
@EnableCircuitBreaker
public class SpringCloudUserApplication {
  
  public static void main(String[] args) {
    SpringApplication.run(SpringCloudUserApplication.class, args);
  }
}

application.yml

feign:
    hystrix:
        enabled: true

hystrix:
    command:
        default:
            circuitBreaker:
                enabled: true
                requestVolumeThreshold: 20
                errorThresholdPercentage: 50
                sleepWindowInMilliseconds: 5000
            execution:
                timeout:
                    enabled: true
                isolation:
                    thread:
                        timeoutInMilliseconds: 1000
                        interruptOnTimeout: true
                    semaphore:
                        maxConcurrentRequests: 10
                    strategy: THREAD
            metrics:
                rollingStats:
                    timeInMilliseconds: 10000
        OrderServiceFeignClient#orders():
            execution:
                timeout:
                    enabled: true
                isolation:
                    thread:
                        timeoutInMilliseconds: 3000
                        interruptOnTimeout: true
    threadpool:
        default:
            coreSize: 10
            maximumSize: 10
            allowMaximumSizeToDivergeFromCoreSize: false
            keepAliveTimeMinutes: 1
            maxQueueSize: -1
            queueSizeRejectionThreshold: 5
        spring-cloud-order:
            coreSize: 10
            maximumSize: 10
            allowMaximumSizeToDivergeFromCoreSize: false
            keepAliveTimeMinutes: 1
            maxQueueSize: -1
            queueSizeRejectionThreshold: 10

代码演示3、Hystrix Dashboard

pom.xml

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

application.yml

server:
	port: 8080

management:
  endpoints:
    web:
      exposure:
        include: hystrix.stream
        
hystrix:
	 dashboard:
        proxy-stream-allow-list: 192.168.124.3

此外,启动类加 @EnableHystrixDashboard 注解。然后在浏览器地址输入 http://192.168.124.3:8080/hystrix,进入 Hystrix Dashboard 的页面。

输入 https://192.168.124.3:8080/actuator/hystrix.stream,然后点击 Monitor Stream 按钮。

代码演示4、Turbine

在代码演示三的基础上增加如下:

pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>

application.yml

turbine:
    app-config: spring-cloud-user,spring-cloud-order
    cluster-name-expression: "'default'"
    aggregator:
        cluster-config: default

启动类额外增加 @EnableTurbine 注解。然后在浏览器地址输入 http://192.168.124.3:8080/hystrix,进入 Hystrix Dashboard 的页面。

输入 https://192.168.124.3:8080/actuator/turbine.stream,然后点击 Monitor Stream 按钮。

本文标签: Hystrix