Sentinal(三)流量控制与熔断降级

Sentinel以流量为切入点,以流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。包括核心的独立类库、监控台、丰富的使用场景。

使用场景:秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、实时熔断下游不可用应用等。

实时监控,开源生态(开箱即用且与其他开源框架/库的整合模块),完善的SPI扩展点(实现扩展,快速定制逻辑,如定制规则逻辑、适配数据流等)

  1. 资源管理:应用服务器脚本、静态页面、API接口、文件图片等
  2. 规则配置:允许资源(一般API接口)通过的请求次数,IP黑白名单,应用服务等
  3. 测试效果:QPS(单台服务器每秒能处理查询次数);TPS(每秒处理的事务数,倾向整个过程)

Sentinel分为两部分:

  • 核心库(JAVA客户端)不依赖任何框架/库
  • 控制台(Dashboard)基于Spring boot开发,打包直接运行(不需要额外tomcat等应用容器,该模块目前基于Spring boot运行)

# 下面开始整合框架:Nacos注册中心、Feign服务、Sentinel哨兵、Sentinel控制台

一、Sentinel入门介绍

# 搭建2.2.5.RELEASE(与上一文搭建Nacos选了1.4.1版本)sentinel按下图选择的1.8.0版本,下载地址:https://github.com/alibaba/Sentinel/releases

下载到本地后,执行 javaw -jar sentinel-dashboard-1.8.0.jar 默认端口8080( 如果8080端口被占用,可以自定义启动端口java -jar xxx.jar --server.port=8888)linux 后台启动可以执行 nohup java -jar xxx.jar >log.log & 指定日志文件位置和后台挂起启动

启动成功后访问地址:http://ip:port 默认用户名密码:sentinel

二、搭建Sentinel项目

现在创建一个cloudalbb-sentinel-ribbon1020项目,项目里基本依赖和配置如下:

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
server:
  port: 1020


spring:
  application:
    name: sentinel-ribbon1020
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nacos集群,使用的是域名
    sentinel:
      transport:
        dashboard: localhost:8080 #配置sentinel dashboard地址
        port: 8719 #默认8719端口

service-url:
  nacos-service: http://nacos-provider

1、只配置单个blockHandler限流降速处理方法配置

 @GetMapping("/request/pay/{id}")
 @SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
    public CommonResult<Order> reqToPay(@PathVariable("id") Long id){

        CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);

        return result;
    }


    public CommonResult<Order> blockHandler(@PathVariable("id") Long id, BlockException exception){
        // 不同的异常返回不同的提示语
        String reason = "";
        if (exception instanceof FlowException) {
            reason = "接口限流了";
        } else if (exception instanceof DegradeException) {
            reason = "服务降级了";
        } else if (exception instanceof ParamFlowException) {
            reason = "热点参数限流了";
        } else if (exception instanceof SystemBlockException) {
            reason = "触发系统保护规则";
        } else if (exception instanceof AuthorityException) {
            reason = "授权规则不通过";
        }
        Order order = new Order(id, "默认值");
        return new CommonResult<Order>(521, "收到请求id:"+id+",sentinel-blockHandler"+reason+":"+exception.getMessage(), order);
    }

将nacos-provider和sentinel-ribbon2010两个项目启动,然后配置流量降速,最后访问一下

2、加个blockHandlerClass限流降级处理类配置

为了提高代码的可读性及解耦,将自定义限流降速方法写入一个限流降速级类中,需要时再调用(所有的方法均为static静态方法,参数必须带上BlockException,否则找不到响应方法), blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析

@GetMapping("/request/pay/{id}")
@SentinelResource(value = "fallback",blockHandler = "blockHandler",blockHandlerClass = BlockHandler.class) //blockHandler只负责sentinel控制台配置违规
    public CommonResult<Order> reqToPay(@PathVariable("id") Long id){

        CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);

        return result;
    }

3、只配置单个fallback熔断降级方法配置

defaultFallback,默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。

@GetMapping("/request/pay/{id}")
@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
    public CommonResult<Order> reqToPay(@PathVariable("id") Long id){

        CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);

        int test = 10/0;

        return result;
    }

    public CommonResult<Order> handlerFallback(@PathVariable("id") Long id, Throwable throwable){
        Order order = new Order(id, "默认值");
        return new CommonResult<Order>(520, "收到请求id:"+id+",业务异常:"+throwable.getMessage(), order);
    }

4、加个fallbackClass熔断降级处理类配置

@GetMapping("/request/pay/{id}")
@SentinelResource(value = "fallback",fallback = "handlerFallback",fallbackClass=CustomerFallback.class) //fallback只负责业务异常
    public CommonResult<Order> reqToPay(@PathVariable("id") Long id){

        CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);

        int test = 10/0;

        return result;
    }

    public CommonResult<Order> handlerFallback(@PathVariable("id") Long id, Throwable throwable){
        Order order = new Order(id, "默认值");
        return new CommonResult<Order>(520, "收到请求id:"+id+",业务异常:"+throwable.getMessage(), order);
    }

5、blockHandler和fallback可以同时配置,不再赘述

exceptionsToIgnore,用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

 @GetMapping("/request/pay/{id}")
//    blockHandler/blockHandlerClass流速降级,fallback/fallbackClass熔断降速
//    @SentinelResource(value="fallback") //无配置
//    @SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
//    @SentinelResource(value = "fallback",fallback = "customerFallback",fallbackClass = CustomerFallback.class) //独立的业务异常处理
//    @SentinelResource(value = "fallback",defaultFallback = "defaultFallback") //通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)
//    @SentinelResource(value = "fallback",defaultFallback = "customerDefaultFallback",fallbackClass = DefaultFallBack.class) //通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)
//    @SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
    @SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler", exceptionsToIgnore = {IllegalArgumentException.class} )  //异常被排除掉,不会进入fallback逻辑中,而是会原样抛出。
    public CommonResult<Order> reqToPay(@PathVariable("id") Long id){

        CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);

        int test = 10/0;

        return result;
    }

三、集成Spring Cloud OpenFeign

Service层进行注解配置:

@FeignClient(value = "nacos-provider",fallback = PaymentFallbackServiceImpl.class)
@Component
public interface PaymentService {

    @GetMapping("/order/{id}")
    public CommonResult<Order> getOrderById(@PathVariable("id")Long id);
}
@Component
public class PaymentFallbackServiceImpl implements PaymentService {

    @Override
    public CommonResult<Order> getOrderById(Long id) {
        return new CommonResult<>(444,"服务降级返回,OrderFallbackService",new Order(id,"errorSerial"));
    }
}

四、集成RestTemplate

@Bean
@LoadBalanced
@SentinelRestTemplate(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class)
public RestTemplate restTemplate() {
    return new RestTemplate();
}

@SentinelRestTemplate 注解的属性支持限流(blockHandler, blockHandlerClass)和降级(fallback, fallbackClass)的处理。

其中 blockHandler 或 fallback 属性对应的方法必须是对应 blockHandlerClass 或 fallbackClass 属性中的静态方法。

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