基于Sentinel的服务保护

通用资源保护

引入依赖
需要注意SpringCloud-Alibaba与SpringCloud的版本关系

 父工程引入 alibaba实现的SpringCloud

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

子工程中引入 sentinel

<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

( 3) 配置熔断降级方法

    @SentinelResource(value="orderFindById",blockHandler = "orderBlockHandler",fallback = "orderFallback")
    @RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
    public Product findById(@PathVariable Long id) {
        if(id != 1) {
            throw new RuntimeException("错误");
        }
        return restTemplate.getForObject("http://service-product/product/1",Product.class);
    }


    /**
     * 定义降级逻辑
     *  hystrix和sentinel
     *      熔断执行的降级方法
     *      抛出异常执行的降级方法
     */
    public Product orderBlockHandler(Long id) {
        Product product = new Product();
        product.setProductName("触发熔断的降级方法");
        return product;
    }

    public Product orderFallback(Long id) {
        Product product = new Product();
        product.setProductName("抛出异常执行的降级方法");
        return product;
    }

@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource注解包含以下属性:

  • value:资源名称,必需项(不能为空)
  • entryType:entry 类型,可选项(默认为 EntryType.OUT
  • blockHandler / blockHandlerClassblockHandler 对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  • fallback:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:
    • 返回值类型必须与原函数返回值类型一致;
    • 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
    • fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  • defaultFallback(since 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:
    • 返回值类型必须与原函数返回值类型一致;
    • 方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
    • defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  • exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

注:1.6.0 之前的版本 fallback 函数只针对降级异常(DegradeException)进行处理,不能针对业务异常进行处理。

特别地,若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。若未配置 blockHandlerfallback 和 defaultFallback,则被限流降级时会将 BlockException 直接抛出(若方法本身未定义 throws BlockException 则会被 JVM 包装一层 UndeclaredThrowableException)。

进行测试:

 

 

 先执行2,在5秒里面返回都是这个。

加载本地配置

  cloud:
    sentinel:
      transport:
        dashboard: 192.168.180.137:8887   #sentinel控制台的请求地址
      datasource:
        ds1:
          file:
            file: classpath:flowrule.json
            data-type: json
            rule-type: flow
      eager: true #立即加载
[
  {
    "resource": "orderFindById",
    "controlBehavior": 0,
    "count": 1,
    "grade": 1,
    "limitApp": "default",
    "strategy": 0
  }
]

Rest实现熔断
Spring Cloud Alibaba Sentinel 支持对 RestTemplate 的服务调用使用 Sentinel 进行保护,在构造
RestTemplate bean的时候需要加上 @SentinelRestTemplate 注解。

@LoadBalanced
    @Bean
    @SentinelRestTemplate(fallbackClass = ExceptionUtils.class,fallback = "handleFallback",
        blockHandler = "handleBlock" ,blockHandlerClass = ExceptionUtils.class
    )
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

@SentinelRestTemplate 注解的属性支持限流( blockHandler , blockHandlerClass )和降级
( fallback , fallbackClass )的处理。
其中 blockHandler 或 fallback 属性对应的方法必须是对应 blockHandlerClass 或
fallbackClass 属性中的静态方法。
该方法的参数跟返回值跟
org.springframework.http.client.ClientHttpRequestInterceptor#interceptor 方法一
致,其中参数多出了一个 BlockException 参数用于获取 Sentinel 捕获的异常。
比如上述 @SentinelRestTemplate 注解中 ExceptionUtil 的 handleException 属性对应的方法
声明如下:

public class ExceptionUtils {

    /**
     * 静态方法
     *      返回值: SentinelClientHttpResponse
     *      参数 : request , byte[] , clientRquestExcetion , blockException
     */
    //限流熔断业务逻辑
    public static SentinelClientHttpResponse handleBlock(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
        Product product = new Product();
        product.setProductDesc("限流熔断");
        return new SentinelClientHttpResponse(JSON.toJSONString(product));
    }

    //异常降级业务逻辑
    public static SentinelClientHttpResponse handleFallback(HttpRequest request, byte[] body,
        ClientHttpRequestExecution execution, BlockException ex) {
        Product product = new Product();
        product.setProductDesc("异常降级");
        return new SentinelClientHttpResponse(JSON.toJSONString(product));
    }

}

1秒里面都执行几次,就会这样

Feign实现熔断
Sentinel 适配了 Feign 组件。如果想使用,除了引入 sentinel -starter 的依赖外还需要 2 个步骤:
配置文件打开 sentinel 对 feign 的支持: feign.sentinel.enabled=true
加入 openfeign starter 依赖使 sentinel starter 中的自动化配置类生效:

(1) 引入依赖

<!--springcloud整合的openFeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

( 2) 开启sentinel 支持
在工程的application.yml中添加sentinel 对 feign 的支持

feign:
  sentinel:
    enabled: true

( 3)配置FeignClient
和使用Hystrix的方式基本一致,需要配置FeignClient接口以及通过 fallback 指定熔断降级方法

/**
 * 声明需要调用的微服务名称
 *  @FeignClient
 *      * name : 服务提供者的名称
 *      * fallback : 配置熔断发生降级方法
 *                  实现类
 */
@FeignClient(name="service-product",fallback = ProductFeignClientCallBack.class)
public interface ProductFeignClient {

    /**
     * 配置需要调用的微服务接口
     */
    @RequestMapping(value="/product/{id}",method = RequestMethod.GET)
    public Product findById(@PathVariable("id") Long id);
}
@Component
public class ProductFeignClientCallBack implements ProductFeignClient {

    /**
     * 熔断降级的方法
     */
    public Product findById(Long id) {
        Product product = new Product();
        product.setProductName("feign调用触发熔断降级方法");
        return product;
    }
}

Feign 对应的接口中的资源名策略定义:httpmethod:protocol://requesturl。 @FeignClient 注解中的所有属性,Sentinel 都做了兼容。
ProductFeginClient 接口中方法 findById 对应的资源名为 GET: http://shop-service-product/product/{str}。

原文地址:https://www.cnblogs.com/dalianpai/p/12286966.html