Spring Cloud Hystrix

功能

  • 服务降级
    • 优先核心服务,非核心服务弱可用或不可用
    • 具体表现为当调用一个服务不可用或者发生异常时,转到指定降级页面或触发降级信息
    • 通过@HystrixCommand注解指定
    • fallackMethod(回退函数)中实现降级的逻辑
      • 目标服务不可用--降级
      • 本服务出现异常(比如数据库连接过多,或访问量太大)--也可以选择降级
  • 服务熔断
    • 某个服务的错误率到达一定阈值,切断服务
    • 当断路器打开,而服务不可用时,休眠时间窗就开始计时,计时结束后,将熔断器设为半打开,尝试发一次请求,若请求成功,关闭熔断器;若失败,休眠时间窗继续计时
  • 依赖隔离
    • 为每个方法设立一个线程池用于隔离
  • 监控(Hystrix Dashboard)

集成

pom引入依赖

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

启动类添加注解

@EnableCircuitBreaker

服务降级

A服务访问B服务,B服务不可用时,触发降级,转到某静态页面如提示"太拥挤了,请稍后再试"

新建 HystrixController 测试

package com.viki.order.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;

/**
 * @Author Sakura
 * @Date 14/11/2019
 **/
@RestController
public class HystrixController {

    //超时配置
    @HystrixCommand(fallbackMethod = "fallback")  //回调方法名
    @GetMapping("/getProductInfoList")
    public String getProductInfoList() {
  
        //使用RestTemplate 调用其他服务方法名
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject("http://127.0.0.1:8090/product/listForOrder",
                Arrays.asList("10"),
                String.class);

    }

    private String fallback() {
        return "太拥挤了, 请稍后再试~~";
    }
}

也可以指定默认方法

package com.viki.order.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;

/**
 * @Author Sakura
 * @Date 14/11/2019
 **/
@RestController
@DefaultProperties(defaultFallback = "defaultFallback")
public class HystrixController {

    //超时配置
    @HystrixCommand
    @GetMapping("/getProductInfoList")
    public String getProductInfoList() {
  
        //使用RestTemplate 调用其他服务方法名
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject("http://127.0.0.1:8090/product/listForOrder",
                Arrays.asList("10"),
                String.class);

    }

    private String defaultFallback() {
        return "默认提示:太拥挤了, 请稍后再试~~";
    }
}

超时时间配置

默认超时时间是1秒,即在一秒钟之内无法收到返回的结果就会降级。而许多服务的运行时间确实长,所以需要更改超时时间

@HystrixCommand(commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
    })

使用配置项设置

在方法加注解@HystrixCommand的前提下,配置文件中配置

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1000
    getProductInfoList:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000

可使用default统一设置,也可以为具体的方法具体设置,如getProductInfoList

feign-hystrix的使用

配置添加

feign:
  hystrix:
    enabled: true

启动类添加扫描使Feign的包被扫描到

@ComponentScan(basePackages = "com.viki")

Feignclient的配置更改

@FeignClient(name = "product", fallback = ProductClient.ProductClientFallback.class)
public interface ProductClient {

    @PostMapping("/product/listForOrder")
    List<ProductInfoOutput> listForOrder(@RequestBody List<String> productIdList);

    @PostMapping("/product/decreaseStock")
    void decreaseStock(@RequestBody List<DecreaseStockInput> decreaseStockInputList);

    //降级回调函数
    @Component
    static class ProductClientFallback implements ProductClient{

        @Override
        public List<ProductInfoOutput> listForOrder(List<String> productIdList) {
            return null;
        }

        @Override
        public void decreaseStock(List<DecreaseStockInput> decreaseStockInputList) {

        }
    }
}

依赖隔离

Hystrix使用仓壁模式实现了线程池的隔离,会为每个HystrixCommand创建一个独立的线程池,各HystrixCommand之前互相隔离,不会相互影响,自动实现依赖隔离。

服务降级和依赖隔离是一体化实现的

服务熔断

@HystrixCommand(commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),  //设置熔断
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), //在滚动时间窗口中断路器最小请求数
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //休眠时间窗计时时间
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60") //失败率,高于此则打开断路器
    })

主要有4个参数,以上都有注释

整体的效果是:在10秒钟之内,若请求数大于等于10次,其中失败率达到60%,即失败超过6次,熔断器就会开启。此时就会触发降级。

10秒钟结束后,自动发一次请求,若成功,则关闭熔断器,请求会正常;若失败,熔断器保持打开,服务降级。

package com.viki.order.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;

/**
 * @Author Sakura
 * @Date 14/11/2019
 **/
@RestController
@DefaultProperties(defaultFallback = "defaultFallback")
public class HystrixController {

    //当断路器打开,服务不可用,休眠时间窗就开始计时,计时结束后,将熔断器设为半打开,尝试发一次请求,若请求成功,关闭熔断器;若失败,休眠时间窗继续计时
    @HystrixCommand(commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),  //设置熔断
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), //在滚动时间窗口中断路器最小请求数
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //休眠时间窗计时时间
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60") //失败率,高于此则打开断路器
    })
    @GetMapping("/getProductInfoList")
    public String getProductInfoList(@RequestParam("number") Integer number) {
        if(number%2 == 0){
            return "success";
        }

        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject("http://127.0.0.1:8090/product/listForOrder",
                Arrays.asList("10"),
                String.class);

    }

    private String defaultFallback() {
        return "默认提示:太拥挤了, 请稍后再试~~";
    }
}

请求必须携带number参数,若number为偶数,就直接访问成功,显示为success;若number为奇数,就调用服务,此时服务未启动,便失败触发降级。

http://localhost:8081/getProductInfoList?number=1 失败

http://localhost:8081/getProductInfoList?number=2 成功

不断访问失败链接,一直快速访问。此时在访问成功链接,也出现了降级,失败

Dashboard界面查看熔断

pom引入依赖

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

启动类添加注解

@EnableHystrixDashboard

打开上方提到的熔断器,启动项目后网页输入 http://localhost:8081/hystrix 

URL输入 http://localhost:8081/actuator/hystrix.stream

Delay延时设置为2000

Title应用名称设置为Order

点击Monitor Stream

此时访问上述两个链接之一才会显示仪表盘

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章