sentinel

sentinel

服务保护主要是限流熔断降级

sentinel客户端 会连接上 sentinel的控制台,获取到规则,,这些保护策略,,可以存放在nacos,或者zookeeper中,,,规则一旦发生了变更,,会将规则推送到各个服务中...

sentinel默认将流控规则写入到了内存里面,项目一重启,就会失效

sentinel定义的资源
  • 所有的web接口均为资源
  • 声明式:SentinelResource去声明这个方法是个资源
  • 编程式: SphU直接用代码去限流,,捕获异常
sentinel中的规则
  • 流量控制 FlowRule
  • 熔断降级 DegradeRule
  • 系统保护 SystemRule
  • 来源访问控制 AuthorityRule
  • 热点参数 ParamFlowRule

sentinel使用

sentinel服务台: https://sentinelguard.io/zh-cn/docs/dashboard.html

下载sentinel服务台:https://github.com/alibaba/Sentinel/releases

sentinel文档:https://github.com/alibaba/Sentinel/wiki/介绍

java导入sentinel:

xml 复制代码
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

sentinel自定义异常BlockException:

下面有很多实现类,,就是每一种规则违反之后会抛出不同的异常,,比如FlowException,
ParamFlowExcption,DegradeException,AuthorityException,SystemBlockException

这些异常会根据资源方式的不同,进行不同的处理,,,

资源方式:

  • web接口
  • @SentinelResource
  • openfeign调用
  • 编程式调用 SphU
  1. web接口

通过拦截器SentinelWebInterceptor处理,,这个拦截器如果捕获到了异常,,会去触发BlockExceptionHandler去执行相应的逻辑,,sentinel默认给了一个DefaultBlockExceptionHandler,如果需要自定义限流返回的json,,就需要自定义BlockExceptionHandler

java 复制代码
package com.cj.order.exception;

import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.cj.common.R;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;

import java.io.PrintWriter;
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, String resourceName, BlockException e) throws Exception {

        // 设置响应码
        response.setStatus(429); // too many request

        // 这个必须在getWriter前面
        response.setContentType("application/json;charset=utf-8");


        // 返回自定义错误json
        PrintWriter writer = response.getWriter();

        System.out.println("e.getClass() = " + e.getClass());
        R error = R.error(500, resourceName + "被sentinel限制了,原因:" + e.getMessage());

        String json = objectMapper.writeValueAsString(error);

        writer.write(json);

        writer.flush();
        writer.close();

    }
}
  1. @SentinelResource : 标注指定的方法

这个注解的拦截逻辑是写在SentinelResourceAspect切面中,,先获取上面有没有blockHandler属性标记的函数,,如果有就执行,,如果没有,继续找fallback属性标记的函数,,如果也没有,就去找defaultFallback属性对应的函数,,,如果这三个属性都没有设置函数,,直接抛出错误,,

所以使用@SentinelResource需要给他配置一个兜底函数

java 复制代码
 @SentinelResource(value = "createOrder",blockHandler ="createOrderFallback" )
    @Override
    public Order createOrder(Long productId, Long userId) {
        System.out.println("doing....");

//        Product product = getProductFromRemoteWithLoadBalance(productId);
//        Product product = getProductFromRemoteWithLoadBalancerAndAnnotation(productId);

        // feign完成远程调用
        Product product = productFeignClient.getProductById(productId);

        Order order = new Order();
        order.setId(1L);
        BigDecimal totalAmount= product.getPrice().multiply(new BigDecimal(product.getNum()));
        order.setTotalAmount(totalAmount);
        order.setUserId(userId);
        order.setNickName("zhangsan");
        order.setAddress("chengdu");

        List<Product> productList = Arrays.asList(product);

        // 远程查询商品列表
        order.setProductList(productList);
        
        return order;
    }



    // 兜底回调,,跟这个方法的签名一样  ===> 可以多加一个exception参数
    public Order createOrderFallback(Long productId, Long userId, BlockException e) {

        Order order = new Order();
        order.setId(0L);
        order.setNickName("无效订单");
        order.setAddress(e.getMessage());
        return order;
    }

blockHandlerfallback区别:

  • blockHandler : 被sentinel熔断,限流触发的异常
  • fallback : 除了sentinel的错误,,业务出错,,也会执行fallback
  1. OpenFeign远程调用兜底
    openfeign使用的时候,有fallback,,需要配置sentinel的包,才能自动使用降级的逻辑,,
    是因为SentinelFeignAutoConfiguration : 配置了 sentinel和openfeign的整合,,@FeignClient中的fallback,,sentinel会去调这个fallback

4.SphU : 底层代码,,直接编程式的写代码,,如果违背了规则,就会抛出BlockException


流控模式
链路策略

不同的链路对应不同的限流策略,尽管调用的是同一个方法,,在设置限流的时候也能够分链路设置,比如说,一个是普通的创建订单,,不遵循规则,,一个是秒杀的创建订单,需要被限流

需要开启不是同一个上下文: spring.sentinel.web-context-unify=false

关联

一开始限流规则不会生效,,只有当关联的资源被大量访问之后,,对应的限流规则才会生效,,,

比如说: 读和写都是操作数据库,,,当订单量的写比较大的时候,,对读进行限流,,就是优先写,,这就是关联策略,读写是相关的,,仅仅在写的请求比较多的时候,读的限流才会触发。。。

当系统里面出现资源竞争的时候,,一般使用关联策略进行限制

流控效果
快速失败

如果超出了阈值,,直接抛出一个BlockException

Warm up : 预热,冷启动

他一开始不会放你指定的qps那么多请求,,会先放1/3 ,慢慢增加,直到增加到高水位线,,会让系统慢慢适应,不至于,系统还没反应过来,就挂掉了

匀速排队

多余的请求会排队,有一个timeout最大排队时间,,超时的请求会被丢掉,,

漏桶算法

熔断降级 DegradeRule

断路器有三个状态:

  • 关闭
  • 打开
  • half open 半开: 放一个请求过去进行探测,如果放行的这个请求能调用,断路器就关掉
  • 慢调用比例
  • 异常比例
  • 异常数

这个图的意思就是5s之内,请求数大于5,,response time超过1s算慢调用,如果达到了慢调用的阈值,,就熔断x秒,,若干秒之后,发送一个试探请求,如果恢复了,就关闭熔断器,否则,继续熔断

热点规则

本质上还是限流,只是这个限流可以针对具体的参数,,也就是精确到参数级别的限流

比如说:

  1. 秒杀下单,每个用户单独限制qps
  2. 6号是用户vvip,不限制qps,,也能排除指定用户的限流
  3. 不允许访问某个id的商品,,就把这个商品id的规则设置为qps为0
授权规则

只有这些个服务才能调用这个资源,,这个规则没什么用,因为有网关

系统规则

全系统触发,一般不用

相关推荐
sunnyday04262 天前
Spring Cloud Alibaba Sentinel 流量控制与熔断降级实战指南
spring boot·sentinel·springcloud
递归尽头是星辰6 天前
Spring Cloud Alibaba 核心理论体系:Nacos、Sentinel、Seata深度解析
spring cloud·nacos·sentinel·seata·微服务治理
daladongba8 天前
Sentinel的原理与应用
sentinel
liushangzaibeijing8 天前
sentinel动态规则和持久化
sentinel·规则持久化·动态规则
liushangzaibeijing8 天前
Sentinel组件学习使用
sentinel·限流·熔断·服务降级
我是一只小青蛙8888 天前
分布式流量守卫者:Sentinel深度解析
分布式·sentinel
廋到被风吹走11 天前
【Spring】Spring Cloud Gateway 网关架构深度解析:路由、过滤器、限流与 Sentinel 集成
spring·架构·sentinel
xiaolyuh12312 天前
Alibaba Sentinel 全解析
系统架构·sentinel·限流
9***g68712 天前
SpringCloud Gateway 集成 Sentinel 详解 及实现动态监听Nacos规则配置实时更新流控规则
spring cloud·gateway·sentinel