Gm-aaa's blog.

SpringCloudAlibaba之Sentinel流量控制

2024/11/18
loading

Sentinel是什么?

Sentinel 是面向分布式多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量控制流量路由熔断降级系统自适应保护等多个维度来帮助用户保障微服务的稳定性。

Sentinel的历史?

  • 2012 年,Sentinel 诞生,主要功能为入口流量控制。

  • 2013-2017 年,Sentinel 在阿里巴巴集团内部迅速发展,成为基础技术模块,覆盖了所有的核心场景。Sentinel 也因此积累了大量的流量归整场景以及生产实践。

  • 2018 年,Sentinel 开源,并持续演进。

  • 2019 年,Sentinel 朝着多语言扩展的方向不断探索,推出 C++ 原生版本,同时针对 Service Mesh 场景也推出了 Envoy 集群流量控制支持,以解决 Service Mesh 架构下多语言限流的问题。

  • 2020 年,推出 Sentinel Go 版本,继续朝着云原生方向演进。

  • 2021 年,Sentinel 正在朝着 2.0 云原生高可用决策中心组件进行演进;同时推出了 Sentinel Rust 原生版本。同时我们也在 Rust 社区进行了 Envoy WASM extension 及 eBPF extension 等场景探索。

  • 2022 年,Sentinel 品牌升级为流量治理,领域涵盖流量路由/调度、流量染色、流控降级、过载保护/实例摘除等;同时社区将流量治理相关标准抽出到 OpenSergo 标准中,Sentinel 作为流量治理标准实现。

Sentinel 基本概念

资源

资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。

只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。

image.png

  • 资源名=接口的请求路径
  • QPS-指服务器每秒能够响应的查询次数,主要针对查询操作的性能评估

规则

围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。

如何部署?

sentinel是通过jar包的方式运行的,可以去Sentinel的github仓库进行下载

最后通过java -jar xxx.jar的方式运行部署,它默认运行在本地的8080端口。

浏览器输入URL:127.0.0.1:8080访问sentinel的管理面板,用户名和密码都默认为sentinel

流控模式


  1. 直接

    • 可以通过QPS对接口流量进行限制,超过设定的阈值会返回Blocked by Sentinel (flow limiting)
    • 也可以自定义fallback
  2. 关联

    • 涉及至少两个资源;当关联的资源达到阈值时,就限流自己
    • 测试:jmeter
  3. 链路

    • 关于链路我们用一个图来解释

      image.png

    • 如图所示,意思就是当通过不同的方式调用服务A,当某个链路设定的流量限制达到阈值时,对这个链路进行限流

    • 用代码进行测试,创建两个controller表示两个不同的链路,创建一个service表示相同的目的地

      @RestController
      @Slf4j
      public class SentinelController {

      private final DemoService demoService;
      public SentinelController(DemoService demoService) {
      this.demoService = demoService;
      }
      @GetMapping("/sentinel")
      public String sentinelDemo(){
      demoService.demo();
      return "Sentinel Demo";
      }
      @GetMapping("/test")
      public String testDemo(){
      demoService.demo();
      return "Sentinel Demo";
      }

      }
      @Service
      public class DemoService {

      @SentinelResource("demo")
      public void demo(){
      System.out.println("demo");
      }
      }

      然后,要在application.yml 中设置上下文路径代表不同链路

      spring:
      application:
      name: service-sentinel
      cloud:
      nacos:
      server-addr: localhost:8848
      sentinel:
      transport:
      dashboard: localhost:8080
      web-context-unify: false #表示不同上下文路径代表不同的链路,默认为true
      server:
      address: 0.0.0.0
      port: 8899

      image.png

      最后访问快速访问/test 路径进行测试

流控效果


  1. 快速失败

    1. 默认,直接抛出异常
  2. 预热Warm Up

    1. 冷启动,意思就是服务对于接收的请求数缓慢上升,就好像睡觉睡醒后,不可能猛的就要去搬砖,需要一点缓冲时间。这就是冷启动

      image.png

      image.png

    2. 对于这个系统接收请求的初始阈值有一个公式:初始阈值=设定的阈值/冷却因子(默认是3),达到初始阈值之后,经过设定的预热时间,达到系统QPS最大值

    3. 应用场景:秒杀系统在开启瞬间会有很多流量打进来,很有可能会把系统打死,预热的方式就是为了保护系统,相当于一个新手保护期

  3. 排队等待

    1. 当大量请求进来时,根据设定的QPS阈值,挨个处理请求,将其他请求先搁在一边,等一会再处理请求

      image.png

熔断规则


是什么?

一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。

例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的

如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。

现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。

以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。

熔断策略


  1. 慢调用比例
    1. 顾名思义,就是当一定量的请求中,满足设定的满调用请求数>设定的比例 时,触发熔断降级。
    2. 设置RT(response time),即为响应时间超过RT时,判定该请求是一次慢调用
    3. 设置统计时长最小请求数,意思是:当单位统计时长 中的请求数大于最小请求数 才进行熔断与否的判定
    4. 设置比例阈值(0~1) 和熔断时长,当进入判定阶段,如果慢调用请求所占统计时长 中总请求的比例>比例阈值 时,则会在接下来的熔断时长 自动熔断接下来的请求。经过熔断时长 后,熔断器会进入探测恢复状态(HALF-OPEN) ,若接下来的一个请求响应时间小于RT 则结束熔断,否则将再次进入熔断状态
  2. 异常比例
    1. 顾名思义,和慢调用类似,只不过是出现异常的比例
  3. 异常数
    1. 异常比例 的区别是一个是异常所占请求的比例,一个是在异常出现的数量上做限制

@SentinelResource注解


是什么?

SentinelResource 是一个流量防卫防护组件注解,用于指定防护资源,对配置的资源进行流量控制、熔断降级等功能。这是它的源码。

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface SentinelResource {
//指定资源的名称
String value() default "";

//入口绑定的模式(inbound/outbound),默认是outbound
EntryType entryType() default EntryType.OUT;

//资源分类,默认为0
int resourceType() default 0;
//处理blockException的函数名称;函数要求(重要):
//1.必须是public
//2.返回类型参数与原方法保持一致
//3.默认需要与原方法在同一个类中,若希望使用其他类的函数。可配置blockHandlerClass,并指定blockHandlerClass里面的方法
String blockHandler() default "";
//存放blockHeadler的类,对应的处理函数必须static修饰
Class<?>[] blockHandlerClass() default {};
//服务降级,用于在抛出异常时提供fallback的处理逻辑,fallback函数可以针对所有类型的异常(除了exceptionsToIgnore排除掉的异常类型)
//1.返回类型与原方法一直
//2.参数类型和原方法相匹配
//3.默认需要和原方法在同一个类中,若希望使用其他类的函数,可配置fallBackClass,并指定fallBackClass中的方法
String fallback() default "";

String defaultFallback() default "";

Class<?>[] fallbackClass() default {};
//需要trace的异常
Class<? extends Throwable>[] exceptionsToTrace() default {Throwable.class};
//指定排除忽略掉哪些异常。排除的异常不会计入异常统计。也不会进入fallback逻辑,而是原样抛出
Class<? extends Throwable>[] exceptionsToIgnore() default {};
}

fallback与blockHandler的区别


  • blockHandler:控制流量达到阈值时的处理逻辑
  • fallback:JVM抛出异常的异常服务降级,返回自定义的服务降级处理
  • 两者可以共存

热点规则


是什么?

为高频热点访问的数据配置的规则,如短期内对单条数据的高频访问,可以为其设置热点规则。控制流量规则。

如何配置?

通过@sentinelResource注解指定资源名

  • 参数索引:从0开始,第几个参数

image.png

只要参数中带有参数索引指定的参数的情况下,会被热点规则管理。

CATALOG
  1. 1. Sentinel是什么?
  2. 2. Sentinel的历史?
  3. 3. Sentinel 基本概念
    1. 3.1. 资源
    2. 3.2. 规则
  4. 4. 如何部署?
    1. 4.1. 流控模式
    2. 4.2. 流控效果
  5. 5. 熔断规则
    1. 5.1. 是什么?
    2. 5.2. 熔断策略
  6. 6. @SentinelResource注解
    1. 6.1. 是什么?
    2. 6.2. fallback与blockHandler的区别
  7. 7. 热点规则
    1. 7.1. 是什么?
    2. 7.2. 如何配置?