Sentinel的初步学习(2)

Sentinel的初步学习(1)https://blog.csdn.net/BinXNoob/article/details/106432595

系统自适应限流

系统规则

https://github.com/alibaba/Sentinel/wiki/%E7%B3%BB%E7%BB%9F%E8%87%AA%E9%80%82%E5%BA%94%E9%99%90%E6%B5%81

系统保护规则是从应用级别的入口流量进行控制,从单台机器的 load、CPU 使用率、平均 RT、入口 QPS 和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(EntryType.IN),比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。

系统规则支持以下的模式:

  • Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5。
  • CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
  • 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
  • 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  • 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。

测试(全局QPS配置)

在这里插入图片描述

设置系统规则

规定该端口下的所有请求

1秒钟只允许1个资源数通过

这时后,无论你哪个资源请求

再1秒钟的访问量超过阈值,则降级

在这里插入图片描述

7.SentinelResource配置

1.按资源名称 + 后续处理

我们给个资源请求,令sentinel控制台获取他的请求

@RestController
public class RateLimitController {

    @GetMapping("/byResource")
    @SentinelResource(value = "byResource",blockHandler = "HandlerException")
    public CommonResult byResource(){
        return new CommonResult(200,"按资源限流进行测试",new Payment(2020L,"serial2020"));
    }

    public CommonResult HandlerException(BlockException exception){
        return new CommonResult(400,exception.getClass().getCanonicalName()+"\t 服务不可用");
    }
}

这个时候我们按照资源名称在sentinel控制台配置上流量限制

在这里插入图片描述

这种情况下,1秒钟限制我们只能一次访问,超过就限流

在这里插入图片描述

我们可以发现

com.alibaba.csp.sentinel.slots.block.flow.FlowException

这是因为我们得BlockException由Alibaba自带得FlowException限流来处理(及时包圆,源码中的一个方法)

发现一个问题

当我们关闭服务后,在去访问sentinel控制台,会发现得我们的资源名,流控规则消失

2.按URL地址限流 + 后续处理

/*
    *  这是对按 URL 地址限流
    *  在控制台配置的是GetMapping中得value
    * */
    @GetMapping("/url")
    @SentinelResource("url")
    public CommonResult byUrl(){
        return new CommonResult(200,"这是对于URL进行资源限流控制测试",new Payment(2020L,"serial2020"));
    }

在这里要和资源名限流分开来

url地址限流是对于 @GetMapping("/url")进行配置,在控制台得资源名指的是@GetMapping("/url")

在这里插入图片描述

当你超过阈值后,

在这里插入图片描述

这里又出现第二个问题

我们发现我们给我们得URL方法配上一个兜底方法后,超阈值访问后,还是不会返回自己的方法,而是系统默认的

写路径情况, 不走自定义的兜底方法。

3.配置全局兜底方法,减少代码耦合的

全局兜底方法

public class MyHandler {
    public static CommonResult handlerException(BlockException e){
        return new CommonResult(444,"按照客户的自定义全局配置Exception==================1");
    }
    public static CommonResult handlerException2(BlockException e){
        return new CommonResult(444,"按照客户的自定义全局配置Exception==================2");
    }
}




设置一个请求配置
  /*
    *  这是用于配置全局自定义异常处理信息
    *  blockHandlerClass  指定我们的异常信息类
    *  blockHandler       指定异常信息类中的异常信息处理方法
    * */
  @GetMapping("/consumerHandler")
    @SentinelResource(value = "consumerHandler",
                      blockHandlerClass = MyHandler.class,
                      blockHandler = "handlerException2")
    public CommonResult consumerHandeler(){
        return new CommonResult(200,"这是对于用户自定义配置的正常访问请求",new Payment(2020L,"serial2020"));
    }

4.SentinelResource注解

详情见官网:https://github.com/alibaba/Sentinel/wiki/%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81

这个注解方式埋点不支持private方法

注意:注解方式埋点不支持 private 方法。

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

  • value:资源名称,必需项(不能为空)

  • entryType:entry 类型,可选项(默认为 EntryType.OUT

  • blockHandler / blockHandlerClass: blockHandler对应处理 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 处理逻辑。若未配置 blockHandlerfallbackdefaultFallback,则被限流降级时会将 BlockException 直接抛出(若方法本身未定义 throws BlockException 则会被 JVM 包装一层 UndeclaredThrowableException)。

集合Ribbon测试

我们建立我们的84端口得controller

@RestController
public class OrderController {

    @Resource
    private RestTemplate restTemplate;

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

    @Value("${service-url.nacos-user-service}")
    private String serviceURL;

     @GetMapping("/consumer/fallback/{id}")
     public CommonResult<Payment> fallback(@PathVariable("id")Long id){
        CommonResult<Payment> result = restTemplate.getForObject(serviceURL+"/paymentSQL/"+id,CommonResult.class);

        if(id == 4){
            throw new IllegalArgumentException("IllegalArgumentException============,非法参数异常");
        }else if(result.getData() == null){
            throw new NullPointerException("NullPointerException====================,空指针异常");
        }
        return result;
    }
1.没有配置任何兜底方法------直接报错去到前端得500页面
@SentinelResource(value = "fallback")   // 没有配置任何兜底方法------直接报错去到前端得500页面

这个时候,我们访问/consumer/fallback/4(前提,数据库中id=4,没有数据)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0SqEMJ43-1590758140860)(D:\ssm\ssm学习\typora-user-images\1588389534(1)].png)

2.配置一个fallback兜底方法-------报错进入我们自定义的兜底方法
@SentinelResource(value = "fallback")   // 没有配置任何兜底方法------直接报错去到前端得500页面
    
  /*
    *  返回fallback
    **/
    public CommonResult handlerFallback(@PathVariable Long id,Throwable e){
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(444,"这是我们的自定义兜底方法==========="+e.getMessage(),payment);
    }   
    

在这里插入图片描述

3.配置一个blockHandler方法---------------该方法配置了sentinel控制台的违规操作报错
@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler负责sentinel控制台的违规报错

 /*
    *   handlerFallback
    * */
    public CommonResult blockHandler(@PathVariable Long id, BlockException e){
        Payment payment = new Payment(id,"null");
        return new CommonResult(445,"blockHandler-sentinel 限流,无此流水"+e.getMessage(),payment);
    }

当你访问一个错误连接时,没达到降级的要求时

他由于我们没有配置fallback方法

直接给我们调回一个错误页面

在这里插入图片描述
当我们访问错误连接到达降级要求时

返回自定义的兜底方法

在这里插入图片描述

4.开启我们的业务层请求出错和sentinel控制台违规操作的两种自定义服务报错方式
@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler")// 开启了我们的业务层请求出错和sentinel的违规报错
    public CommonResult<Payment> fallback(@PathVariable("id")Long id){
        CommonResult<Payment> result = restTemplate.getForObject(serviceURL+"/paymentSQL/"+id,CommonResult.class);

        if(id == 4){
            throw new IllegalArgumentException("IllegalArgumentException============,非法参数异常");
        }else if(result.getData() == null){
            throw new NullPointerException("NullPointerException====================,空指针异常");
        }
        return result;
    }

    /*
    *  返回fallback
    **/
    public CommonResult handlerFallback(@PathVariable Long id,Throwable e){
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(444,"这是我们的自定义兜底方法==========="+e.getMessage(),payment);
    }

    /*
    *   handlerFallback
    * */
    public CommonResult blockHandler(@PathVariable Long id, BlockException e){
        Payment payment = new Payment(id,"null");
        return new CommonResult(445,"blockHandler-sentinel 限流,无此流水"+e.getMessage(),payment);
    }
1.这个时候,当我们访问正确的连接请求,且做出违规操作时,触发降级

在这里插入图片描述

直接返回我们的自定义sentinel控制台方法

2.当我们访问错误的请求连接,触发服务层错误时

在这里插入图片描述

也返回我们的自当以兜底方法

3.当我们访问错误页面,然后做出sentinel控制台的违规操作时

在这里插入图片描述

这是为什么?

先进入了sentinel控制台的报错

因为这是Sentinel异常,因为Sentinel是控制请求的,请求还没到业务内之前就被Sentinel给拦了

4.排除属性-----------------这里排除异常
  exceptionsToIgnore = {IllegalArgumentException.class}

在SentinelResource中有这个属性,这个属性用来排除异常

这里我们排除了id=4的异常
 if(id == 4){
            throw new IllegalArgumentException("IllegalArgumentException============,非法参数异常");
            
            所以,当我们运行起来后,访问id=4的请求页面时,会去到默认的前端500页面

在这里插入图片描述

集合OpenFegin测试

OpenFegin=======也就是service完成一些任务集成,controller只完成简单业务访问

修改我们的84端口

POM文件添加feign 的依赖

yml要激活sentinel对于feign的支持

  # 激活sentinel对feign的支持
feign:
  sentinel:
    enabled: true
    
    
    <!--   openfeign     -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

添加我们的service业务层

service接口
@FeignClient(value = "provider-payment-service",fallback = PaymentServiceImpl.class)
public interface PaymentService {

    @GetMapping("/paymentSQL/{id}")
     public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}



serviceImpl
@Component
public class PaymentServiceImpl implements PaymentService {
    @Override
    public CommonResult<Payment> paymentSQL(Long id) {
        return new CommonResult<>(456,"这是我们的自定义兜底方法=======PaymentServiceImpl"+id,new Payment());
    }
}

修改我们的controller

@RestControllerpublic class FeignController {    
    @Resource    
    private PaymentService paymentService; 
    
    @GetMapping("/consumer/paymentSQL/{id}")    
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id){        
        return paymentService.paymentSQL(id);   
    }
}
测试84 调用 9004 , 此时 故意关闭 9004 微服务提供者,看看消费侧自动降级

在这里插入图片描述

5.熔断框架对比

SentinelHystrixresilience4j
隔离策略信号量隔离(并发线程数限流)线程池隔离/信号量隔离信号量隔离
熔断降级策略基于时间响应、异常比率、异常数基于异常比率基于异常比率、响应时间
实时统计实现滑动窗口(LeapArray)滑动窗口(基于RxJava)Ring Bit Buffer
动态规则配置支持多种数据源支持多种数据源有限支持
扩展性多个扩展点插件形式接口形式
基于注解的支持支持支持支持
限流基于QPS、支持基于调用关系的限流有限的支持Rate Limiter
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值