04-Sentinel

什么是Sentinel?

Sentinel 是阿里巴巴开源的一款轻量级的流量控制和熔断降级框架。它主要用于保护分布式系统中的微服务、API 网关等,以保证系统的稳定性和可靠性。

Sentinel 提供以下核心功能:

  1. 流量控制:可以通过配置规则对进入系统的流量进行实时监控和控制。可以根据不同的流量指标(如 QPS、线程数等)进行限流。当流量超出设定的阈值时,可以执行流量控制策略,如拒绝请求、排队等。

  2. 熔断降级:当某个微服务出现异常或响应时间过长时,可以通过配置熔断规则来快速进行降级,减少请求对下游服务的影响。当熔断条件满足时,可以执行快速失败、返回默认值等策略。

  3. 系统自适应保护:根据系统的实时负载情况,自动调整流量控制和熔断降级的阈值。通过动态调整阈值,保护系统免受过载的影响。

  4. 统计监控:对系统的实时流量、熔断降级情况进行统计和监控。可以通过 Sentinel 的控制台和监控页查看实时的统计信息,方便开发人员对系统进行监控和分析。

一、Sentinel接入

参考文档:https://github.com/alibaba/spring-cloud-alibaba/blob/2022.x/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md

  1. 首先,修改 pom.xml 文件,引入 Sentinel starter。

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

  2. 接入限流埋点

    1. HTTP 埋点

      1. Sentinel starter 默认为所有的 HTTP 服务提供了限流埋点,如果只想对 HTTP 服务进行限流,那么只需要引入依赖,无需修改代码。

    2. 自定义埋点

      1. 如果需要对某个特定的方法进行限流或降级,可以通过 @SentinelResource 注解来完成限流的埋点,示例代码如下:

         @SentinelResource("resource")
         public String hello() {
             return "Hello";
         }
      2. 当然也可以通过原始的 SphU.entry(xxx) 方法进行埋点

        Entry entry = null;
        // 务必保证 finally 会被执行
        try {
          // 资源名可使用任意有业务语义的字符串,注意数目不能太多(超过 1K),超出几千请作为参数传入而不要直接作为资源名
          // EntryType 代表流量类型(inbound/outbound),其中系统规则只对 IN 类型的埋点生效
          entry = SphU.entry("自定义资源名");
          // 被保护的业务逻辑
          // do something...
        } catch (BlockException ex) {
          // 资源访问阻止,被限流或被降级
          // 进行相应的处理操作
        } catch (Exception ex) {
          // 若需要配置降级规则,需要通过这种方式记录业务异常
          Tracer.traceEntry(ex, entry);
        } finally {
          // 务必保证 exit,务必保证每个 entry 与 exit 配对
          if (entry != null) {
            entry.exit();
          }
        }
        1. SphU.entry() 的参数描述:

          参数名

          类型

          解释

          默认值

          entryType

          EntryType

          资源调用的流量类型,是入口流量(EntryType.IN)还是出口流量(EntryType.OUT),注意系统规则只对 IN 生效

          EntryType.OUT

          count

          int

          本次资源调用请求的 token 数目

          1

          args

          Object[]

          传入的参数,用于热点参数限流

  3. 配置限流规则

    1. Sentinel 提供了两种配置限流规则的方式:代码配置 和 控制台配置

      1. 通过代码来实现限流规则的配置。一个简单的限流规则配置示例代码如下

        List<FlowRule> rules = new ArrayList<FlowRule>();
        FlowRule rule = new FlowRule();
        rule.setResource("自定义资源名");
        // set limit qps to 10
        rule.setCount(10);
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setLimitApp("default");
        rules.add(rule);
        FlowRuleManager.loadRules(rules);

二、Sentinel控制台

  1. 整合SpringCloudAlibaba

    1. 首先需要获取 Sentinel 控制台,支持直接下载和源码构建两种方式。

      1. 直接下载:下载 Sentinel 控制台

      2. 源码构建:进入 Sentinel Github 项目页面,将代码 git clone 到本地自行编译打包,参考此文档

    2. 启动控制台

      1. 执行 Java 命令完成 Sentinel 控制台的启动。 控制台默认的监听端口为 8080。Sentinel 控制台使用 Spring Boot 编程模型开发,如果需要指定其他端口,请使用 Spring Boot 容器配置的标准方式,详情请参考 Spring Boot 文档

        1. 启动命令:java -jar sentinel-dashboard.jar,常用参数:

          1. -Dcsp.sentinel.dashboard.server:指定 Sentinel 控制台的地址和端口,默认为 localhost:8080。
            例如:-Dcsp.sentinel.dashboard.server=localhost:8080

          2. -Dproject.name:指定当前应用的名称,用于在 Sentinel 控制台中标识该应用,默认为 sentinel。
            例如:-Dproject.name=myApp

          3. -Dcsp.sentinel.api.port:指定 Sentinel 服务器的监听端口,默认为 8729。
            例如:-Dcsp.sentinel.api.port=9999

          4. -Dcsp.sentinel.log.dir:指定 Sentinel 日志文件的存储路径,默认为 logs。

          5. -Dcsp.sentinel.log.use.pid:是否在 Sentinel 日志文件名中显示进程 ID,默认为 false。

          6. -Dcsp.sentinel.metric.file.name:指定 Sentinel 指标文件的存储路径,默认为data/metrics.log。

    3. 增加配置

      spring.cloud.sentinel.transport.dashboard=localhost:8080
    4. 访问页面

      1. http://localhost:8080

  2. 菜单说明

    1. 实时监控:控制台可以实时展示应用程序的实时监控数据,包括流量、响应时间、异常等指标。您可以通过可视化的图表和表格来进行实时观察和分析。

    2. 簇点链路:用于配置和管理分布式系统中的节点拓扑结构,包括集群的创建、节点的添加和设置主备关系等。

    3. 流控规则:用于配置应用程序的流量控制规则。您可以设置每秒通过的请求总数、并发线程数、QPS(每秒钟的请求数量)等参数,以保护应用程序免受过载的影响。

    4. 降级规则:用于配置应用程序的降级规则。当系统资源紧张或出现异常情况时,您可以通过设置降级规则,将某些功能或接口进行限制或临时关闭,以保证核心功能的稳定和可用性。

    5. 系统规则:用于配置应用程序的系统保护规则。系统规则是在应用程序整体触发条件下进行流控的规则,例如平均响应时间超过阈值等。它可用于保护系统免受异常请求影响以及一些自定义的系统级别的保护。

    6. 机器列表:列出已注册到 Sentinel 控制台的所有机器信息。您可以查看每台机器的 IP 地址、端口号、心跳信息和最近的运行状态。

三、Sentinel集群

@TODO

四、规则种类

Sentinel 的所有规则都可以在内存态中动态地查询及修改,修改之后立即生效。同时 Sentinel 也提供相关 API,供您来定制自己的规则策略。

Sentinel 支持以下几种规则:流量控制规则熔断降级规则系统保护规则来源访问控制规则 和 热点参数规则

  1. 流量控制规则 (FlowRule)

    1. 使用场景

      1. 保护核心资源:在高并发场景下,保护核心资源免受过多请求的冲击。通过设置流控规则,可以限制每秒通过的请求数量或并发线程数,从而确保核心资源的稳定运行。

      2. 防止雪崩效应:当系统中某个服务或接口出现故障或延迟,流控规则可以帮助限制对该服务或接口的访问,避免过多的请求堆积在该服务上,从而防止雪崩效应的发生。

      3. 平滑过载限流:在系统资源紧张的情况下,通过设置流控规则可以实现平滑的限流,将超过阈值的请求进行逐步拒绝或延迟处理,以保护系统的稳定性和避免系统崩溃。

      4. 限制外部请求:对于某些公共接口或第三方依赖接口,通过流控规则可以限制外部请求,防止恶意攻击、爬虫或过度使用,确保资源的合理分配和保护。

      5. 防御漏洞利用:当系统存在某些漏洞时,恶意用户可能会通过短时间内发送大量请求来利用漏洞。流控规则可以设置合理的阈值来限制高频率的请求,并减少漏洞的利用。

    2. 用于限制资源(接口或方法)的访问流量。同一个资源可以同时有多个限流规则,检查规则时会依次检查。

    3. 通过代码定义流量控制规则

      1. 我们可以通过调用 FlowRuleManager.loadRules() 方法来用硬编码的方式定义流量控制规则

        private void initFlowQpsRule() {
            List<FlowRule> rules = new ArrayList<>();
            FlowRule rule = new FlowRule(resourceName);
            // set limit qps to 20
            rule.setCount(20);
            rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
            rule.setLimitApp("default");
            rules.add(rule);
            FlowRuleManager.loadRules(rules);
        }
      2. 属性:

        Field

        说明

        默认值

        resource

        资源名,资源名是限流规则的作用对象

        count

        限流阈值

        grade

        限流阈值类型,QPS 模式(1)或并发线程数模式(0)

        QPS 模式

        limitApp

        流控针对的调用来源

        default,代表不区分调用来源

        strategy

        调用关系限流策略:直接、链路、关联

        根据资源本身(直接)

        controlBehavior

        流控效果(直接拒绝/WarmUp/匀速+排队等待),不支持按调用关系限流

        直接拒绝

        clusterMode

        是否集群限流

    4. 控制台操作流控

      1. 流控模式

        1. 直接(Direct):直接流控模式指的是对某个资源或接口直接进行流量控制,不依赖其他资源的状态或流量情况。该模式适用于针对某个具体资源的流控需求,设置的流控规则只与该资源相关。

        2. 关联(Association):关联流控模式用于将多个流控规则进行逻辑关联,通过逻辑运算符(例如与AND、或OR)来组合不同规则的判断结果。关联流控模式可以实现更复杂的流控策略,根据多个规则的综合判断来限制流量。

        3. 链路(Chain):链路流控模式是用于对多个请求进行整体流控的模式,即根据请求的调用链路信息来判断是否进行限流。在分布式系统中,链路流控可以实现对请求发起方或传递方所在的整个调用链进行流控,保护系统免受异常请求的影响。

      2. 流控方式

        1. 直接拒绝(Reject):当达到流控阈值后,直接拒绝请求,返回错误信息。这种模式的流控效果是立即拒绝请求,对系统的访问速度有较为明显的影响。

        2. 预热(Warm Up):在一定时间内,逐渐将通过请求数量逐步增加。预热模式的流控效果是让系统在启动或重启时,逐渐承受更多的请求,避免系统因突发流量而过载。

        3. 排队等待(Queue):当达到流控阈值后,将请求加入队列中等待处理。排队等待模式的流控效果是保证请求的有序处理,适用于需要有序处理请求的场景。

  2. 熔断降级规则 (DegradeRule)

    1. 使用场景

      1. 保护依赖服务:当系统依赖的某个服务出现故障或延迟过高时,可以通过熔断规则暂时地停止对该服务的请求,防止级联故障,同时保护系统的稳定性。

      2. 防止雪崩效应:当某个服务发生故障或过载时,会导致大量请求堆积在该服务上,进而影响到整个系统的稳定性。通过熔断规则可以及时停止对该服务的请求,避免雪崩效应的扩散。

      3. 容错和降级:在复杂的分布式系统中,不同的服务之间可能存在依赖关系。当某个服务不可用时,可以通过熔断规则快速进行容错和降级,保证核心业务功能的正常运行。

      4. 限流和故障恢复:通过设置熔断规则,可以限制对故障服务的访问,从而保护系统资源和其他关键服务。同时,当服务恢复正常时,熔断规则可以帮助系统逐渐恢复正常的请求流量。

    2. 用于在异常情况下对资源的访问进行降级处理,同一个资源可以同时有多个降级规则

    3. 通过代码定义流量控制规则

      1. 可以通过调用 DegradeRuleManager.loadRules() 方法来用硬编码的方式定义流量控制规则

        private void initDegradeRule() {
            List<DegradeRule> rules = new ArrayList<>();
            DegradeRule rule = new DegradeRule();
            rule.setResource(KEY);
            // set threshold RT, 10 ms
            rule.setCount(10);
            rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
            rule.setTimeWindow(10);
            rules.add(rule);
            DegradeRuleManager.loadRules(rules);
        }
      2. 属性:

        Field

        说明

        默认值

        resource

        资源名,即规则的作用对象

        grade

        熔断策略,支持慢调用比例/异常比例/异常数策略

        慢调用比例

        count

        慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值

        timeWindow

        熔断时长,单位为 s

        minRequestAmount

        熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入)

        5

        statIntervalMs

        统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入)

        1000 ms

        slowRatioThreshold

        慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)

    4. 控制台操作降级

      1. 阈值类型

        1. RT(平均响应时间):以接口或服务的平均响应时间为基准,当平均响应时间超过设定的阈值时,触发降级。

        2. 异常比例(Error Ratio):以接口或服务的异常请求比例为基准,当异常请求比例超过设定的阈值时,触发降级。

  3. 系统保护规则 (SystemRule)

    1. 应用场景

      1. 平均响应时间超过阈值:当系统中某个接口或服务的平均响应时间超过预设的阈值时,可以使用系统规则进行流控。通过设置响应时间的阈值,可以保护系统免受过高的延迟影响,确保系统的稳定性。

      2. 并发线程数超过阈值:当系统中的并发线程数量超过设定的阈值时,可能会导致系统资源过度消耗、性能下降,甚至系统崩溃。使用系统规则设置并发线程数的阈值,可以限制过高的并发量,保护系统资源。

      3. 异常比例超过阈值:在系统运行过程中,如果异常请求比例过高,可能会导致系统出现异常或不可用。通过系统规则设置异常请求比例的阈值,可以控制异常请求的影响,保证系统的可用性。

      4. 系统负载过高:当系统负载过高时,可能会导致系统响应变慢、资源使用率上升。使用系统规则设置系统负载的阈值,可以对系统负载进行控制和保护,确保系统的稳定性和可用性。

    2. 通过代码定义流量控制规则

      1. 可以通过调用 SystemRuleManager.loadRules() 方法来用硬编码的方式定义流量控制规则

        private void initSystemRule() {
            List<SystemRule> rules = new ArrayList<>();
            SystemRule rule = new SystemRule();
            rule.setHighestSystemLoad(10);
            rules.add(rule);
            SystemRuleManager.loadRules(rules);
        }
      2. 属性:

        Field

        说明

        默认值

        highestSystemLoad

        load1 触发值,用于触发自适应控制阶段

        -1 (不生效)

        avgRt

        所有入口流量的平均响应时间

        -1 (不生效)

        maxThread

        入口流量的最大并发数

        -1 (不生效)

        qps

        所有入口资源的 QPS

        -1 (不生效)

        highestCpuUsage

        当前系统的 CPU 使用率(0.0-1.0)

        -1 (不生效)

    3. 控制台操作系统保护规则

  4. 热点参数限流

    1. 应用场景

      1. 秒杀/抢购场景:在秒杀或抢购活动中,热点参数通常是商品ID或活动ID,这些参数会集中在短时间内受到大量请求。通过热点参数规则可以限制这些热门活动或商品的访问频率,避免系统崩溃或性能下降。

      2. 用户个人主页访问:在社交网络或电子商务平台中,用户个人主页访问往往是热点操作,可能会导致高并发请求。通过热点参数规则可以控制同一用户访问个人主页的频率或并发量,保护系统免受个人主页访问的高压力影响。

      3. 车次余票查询:在火车票或飞机票订购系统中,用户常常会查询某个车次的余票情况,这些车次号是热点参数。通过热点参数规则可以限制对热门车次的余票查询频率,避免系统因热点车次的高频查询导致响应延迟。

      4. 地址转换服务:在位置服务或地图导航等应用中,地址转换服务会面临许多热点参数,如地址解析请求。通过热点参数规则可以控制地址解析请求的频率,以保证地址转换服务的稳定性和可用性。

    2. 引入依赖

      <dependency>
          <groupId>com.alibaba.csp</groupId>
          <artifactId>sentinel-parameter-flow-control</artifactId>
          <version>x.y.z</version>
      </dependency>
    3. 通过代码定义流量控制规则

      1. 我们可以通过 ParamFlowRuleManager 的 loadRules 方法更新热点参数规则

        ParamFlowRule rule = new ParamFlowRule(resourceName)
            .setParamIdx(0)
            .setCount(5);
        // 针对 int 类型的参数 PARAM_B,单独设置限流 QPS 阈值为 10,而不是全局的阈值 5.
        ParamFlowItem item = new ParamFlowItem().setObject(String.valueOf(PARAM_B))
            .setClassType(int.class.getName())
            .setCount(10);
        rule.setParamFlowItemList(Collections.singletonList(item));
        
        ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
      2. 属性:

        属性

        说明

        默认值

        resource

        资源名,必填

        count

        限流阈值,必填

        grade

        限流模式

        QPS 模式

        durationInSec

        统计窗口时间长度(单位为秒),1.6.0 版本开始支持

        1s

        controlBehavior

        流控效果(支持快速失败和匀速排队模式),1.6.0 版本开始支持

        快速失败

        maxQueueingTimeMs

        最大排队等待时长(仅在匀速排队模式生效),1.6.0 版本开始支持

        0ms

        paramIdx

        热点参数的索引,必填,对应 SphU.entry(xxx, args) 中的参数索引位置

        paramFlowItemList

        参数例外项,可以针对指定的参数值单独设置限流阈值,不受前面 count 阈值的限制。仅支持基本类型和字符串类型

        clusterMode

        是否是集群参数流控规则

        false

        clusterConfig

        集群流控相关配置

    4. 控制台操作热点规则

五、统一异常处理

可以通过实现BlockExceptionHandler接口来进行统一的异常处理。下面是一个简单的示例代码:

@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
    Logger log= LoggerFactory.getLogger(this.getClass());
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse response, BlockException e) throws Exception {
        log.info("BlockExceptionHandler BlockException================"+e.getRule());

        Result r = null;

        if (e instanceof FlowException) {
            r = Result.error(100,"接口限流了");

        } else if (e instanceof DegradeException) {
            r = Result.error(101,"服务降级了");

        } else if (e instanceof ParamFlowException) {
            r = Result.error(102,"热点参数限流了");

        } else if (e instanceof SystemBlockException) {
            r = Result.error(103,"触发系统保护规则了");

        } else if (e instanceof AuthorityException) {
            r = Result.error(104,"授权规则不通过");
        }
        //返回json数据
        response.setStatus(500);
        response.setCharacterEncoding("utf-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        new ObjectMapper().writeValue(response.getWriter(), r);
    }

六、整合openfeign

  1. 添加依赖

            <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. 添加配置

    #feign与sentinel整合
    feign:
      sentinel:
        enabled: true
  3. 编写feign接口和降级方法

    @FeignClient(name = "stock-nacos",path="/test",fallback = StockFallBackApi.class )
    public interface StockApi {
        @RequestMapping("/test")
        String test();
    }
    
    @Component
    public class StockFallBackApi implements StockApi {
    
        @Override
        public String test() {
            return "降级";
        }
    }
  4. 设置流控规则,调试

七、整合Nacos做规则持久化

  1. nacos配置持久化在sentinel控制台中

    1. 添加依赖

       <dependency>
                  <groupId>com.alibaba.csp</groupId>
                  <artifactId>sentinel-datasource-nacos</artifactId>
              </dependency>
    2. 创建 NacosDataSource 文件

    3. 添加配置

      spring:
        application:
          name: order-nacos
        cloud:
          nacos:
            discovery:
              server-addr: 127.0.0.1:9100
              service: order-nacos
          sentinel:
            transport:
              dashboard: localhost:8080
            datasource:
              nacosData: #自定义名称
                nacos:
                  server-addr: 127.0.0.1:9100
                  username: nacos
                  password: nacos
                  data-id: xxxx   #nacos配置文件
                  rule-type: flow    #规则类型
  2. 修改控制台规则配置持久化在Nacos配置文件中

    1. @TODO

八、gateway整合sentinel

  1. 添加依赖

     <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
            </dependency><dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-datasource-nacos</artifactId>
            </dependency>
  • 22
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值