springcloud-sentinel组件详解

Sentinel

什么是sentinel

​ 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

​ sentinel 中文官网

​ Sentinel 具有以下特征:

丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。

完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。

广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C++ 等多语言的原生实现。

完善的 SPI 扩展机制:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

Sentinel 的主要特性:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c1ODev6J-1667384647255)(…/image/69660d75-8ce1-4a24-916f-003722dff6cc-20764866.jpg)]

Sentinel 分为两个部分:

​ 核心库(Java 客户端): 不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持

​ 控制台(Dashboard): 基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器

Sentinel和Hystrix对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IqBtNNpA-1667384647256)(…/image/5d4ccc56-86f3-4383-9b34-544bb0a8d5b0-20764866.jpg)]

服务使用中的各种问题:

  1. 服务雪崩:由于一个服务发生问题,进而导致整个系统不可用或瘫痪的问题

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-odPgaYCh-1667384647257)(spring%20cloud.assets/image-20221025091600776.png)]

​ 解决雪崩问题的常见方式:

​ 1、超时处理:设定超时时间,请求超过一定的时间没有响应就返回错误信息,不会无休止等待。

​ 2、舱壁模式:限定每个业务能使用的线程数,避免耗尽整个tomcat资源,因此也叫线程隔离。

​ 3、熔断降级:有断路器统计业务执行的异常比例,如果超出阈值则会熔断业务,拦截访问该业务的一切请求。

​ 4、流量控制:限制业务访问的QPS,避免服务因流量的突增而故障。

  1. 服务降级

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bb4FqXAz-1667384647258)(spring%20cloud.assets/image-20221025091438652.png)]

    ​ 服务降级是指 当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理,或换种简单的方式处理,从而释放服务器资源以保证核心业务正常运作或高效运作。说白了,就是尽可能的把系统资源让给优先级高的服务。

    ​ 整个网站处于流量高峰期,服务器压力剧增,根据当前业务情况及流量,对一些服务和页面进行由策略的降级[停止服务,所有的调用直接返回降级数据]。以此缓解服务器资源的压力,以保证核心业务的正常运行,同时也保持了客户和大部分客户得到正确的对应。

  2. 服务熔断

​ 当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。检测到该节点微服务调用响应正常后恢复调用链路。

​ A服务调用 B服务的某个功能,由于网络不稳定问题,或者 B服务卡机,导致功能时间超长。如果这样的次数很多。我们就可以直接将 B服务段路了(A不再请求 B接口),凡是调用 B得直接返回降级数据,不必等待 B的超长执行。这样 B的故障问题,就不会级联影响到 A服务。

​ 4. 服务限流

​ 对打入服务的请求流量进行控制,使服务能够承担不超过自己能力的流量压力

熔断和降级异同:

​ 相同点:

​ 为了保证集群大部分服务的可用性和可靠性,防止崩溃,牺牲小我

​ 用户最终都是体验到某个功能不可用

​ 不同点:

​ 熔断时被调用方故障,触发的系统主动规则

​ 降级是基于全局的考虑,通知一些正常服务,释放资源

Sentinel安装与使用

下载 https://github.com/alibaba/Sentinel/releases

启动

​ 进入下载好的目录,打开cmd,输入命令java -jar sentinel-dashboard-1.7.1.jar启动Sentinel即可

登录

​ 浏览器输入:localhost:8080,即可访问springcloud-sentinel组件详解_第1张图片

​ 默认账号密码都是sentinel,登录成功,安装完成![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zZvM7ZaU-1667384647259)(…/image/cbb8b38c-0896-4b23-be12-7f1843a7c0d9-20764866.jpg)]

引入依赖

	<dependency>
        <groupId>com.alibaba.cspgroupId>
        <artifactId>sentinel-coreartifactId>
    dependency>

controller层

@RestController
@Slf4j
public class HelloController {
    private static final String RESOURCE_NAME="hello";
    private static final String USER_RESOURCE_NAME="user";
    private static final String DEGRADE_RESOURCE_NAME="degrade";
    @RequestMapping("/hello")
    public String hello(){
        Entry entity = null;
        try {
            entity = SphU.entry(RESOURCE_NAME);
            String str = "hello word";
            log.info("===="+str+"====");
            return str;
        } catch (BlockException e1) {
            log.info("block");
            return "被流控了";
        } catch (Exception ex){
            Tracer.traceEntry(ex,entity);
        }finally {
            if (entity != null){
                entity.exit();
            }
        }
        return null;
    }
    @PostConstruct
    public static void initFlowRules(){
        // 流控规则
        List<FlowRule> rules = new ArrayList<FlowRule>();
        // 流控
        FlowRule rule1 = new FlowRule();
        // 设置受保护资源
        rule1.setResource(RESOURCE_NAME);
//        设置流控规则QPS
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
//        设置受保护的资源阈值
        rule1.setCount(1);
        rules.add(rule1);
        FlowRuleManager.loadRules(rules);
    }

缺点:

​ 业务侵入性很强,需要在controller中写入非业务代码.

​ 配置不灵活 若需要添加新的受保护资源 需要手动添加 init方法来添加流控规则

@SentinelResource注解实现

@SentinelResource 注解用来标识资源是否被限流、降级。

​ blockHandler: 定义当资源内部发生了BlockException应该进入的方法(捕获的是Sentinel定义的异常)

​ fallback: 定义的是资源内部发生了Throwable应该进入的方法

​ exceptionsToIgnore:配置fallback可以忽略的异常

​ 源码入口:com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect

引入依赖

<dependency>
	<groupId>com.alibaba.cspgroupId>
	<artifactId>sentinel‐annotation‐aspectjartifactId>
	<version>1.8.0version>
dependency>

controller层

FlowRule rule2 = new FlowRule();
        // 设置受保护资源
        rule2.setResource(USER_RESOURCE_NAME);
//        设置流控规则QPS
        rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
//        设置受保护的资源阈值
        rule2.setCount(1);
        rules.add(rule2);
@PostConstruct
    public void initDegradeRule(){
        List<DegradeRule> degradeRules = new ArrayList<DegradeRule>();
        // 降级规则
        DegradeRule degradeRule = new DegradeRule();
        degradeRule.setResource(DEGRADE_RESOURCE_NAME);
        // 设置规则测率: 异常数
        degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
        // 触发熔断异常数: 2
        degradeRule.setCount(2);
        // 触发熔断最小请求数: 2
        degradeRule.setMinRequestAmount(2);
        // 统计时长: 单位ms
        degradeRule.setStatIntervalMs(60*1000);
        // 熔断持续时长
        degradeRule.setTimeWindow(10);
        degradeRules.add(degradeRule);
        DegradeRuleManager.loadRules(degradeRules);
    }
    @RequestMapping("/user")
    @SentinelResource(value = USER_RESOURCE_NAME,blockHandler = "blockHandlerForGetUser")
    public User getUser(){
        return new User("123");
    }
    public User blockHandlerForGetUser(BlockException ex){
        ex.printStackTrace();
        return new User("流控");
    }
    @RequestMapping("/degrade")
    @SentinelResource(value = DEGRADE_RESOURCE_NAME,entryType = EntryType.IN,blockHandler = "blockHandlerForD")
    public User degrade() throws InterruptedException{
        throw new RuntimeException("异常");
    }

    public User blockHandlerForD(BlockException ex){
        ex.printStackTrace();
        return new User("降级");
    }

Spring cloud alibaba 整合Sentinel

导入依赖

<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>

添加yml配置,为微服务设置sentinel控制台地址

server:
  port: 8061
spring:
  application:
    name: sentinel-order-test
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8858
      web-context-unify: false

在sentinel控制台中设置流控规则

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wvPMkUP8-1667384647260)(…/image/image-20221013155444415.png)]

资源名: 接口的API

针对来源: 默认是default,当多个微服务都调用这个资源时,可以配置微服务名来对指定的微服务设置阈值

阈值类型: 分为QPS和线程数 假设阈值为10

QPS****类型: 只得是每秒访问接口的次数>10就进行限流

线程数: 为接受请求该资源分配的线程数>10就进行限流

当访问/sentinelTest2/test1时 1秒内访问超过2次以上 会限流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UnTmkAYO-1667384647260)(…/image/image-20221013155510317.png)]

sentinel控制台

实时监控

监控接口的通过的QPS和拒绝的QPS

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-00zXm2dQ-1667384647260)(…/image/image-20221013155842958.png)]

簇点链路

用来显示微服务的所监控的API

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZjMge8uU-1667384647261)(…/image/image-20221013155947038.png)]

流控规则

流量控制(flow control),其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,

以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vc6LXrgO-1667384647261)(…/image/image-20221013160111583.png)]

同一个资源可以创建多条限流规则。FlowSlot 会对该资源的所有限流规则依次遍历,直到有规则触发限流或者所有规则遍历完毕。

一条限流规则主要由下面几个因素组成,我们可以组合这些元素来实现不同的限流效果:

Field 说明 默认值
resource 资源名,资源名是限流规则的作用对象
count 限流阈值
grade 限流阈值类型,QPS 模式(1)或并发线程数模式(0) QPS 模式
limitApp 流控针对的调用来源 default,代表不区分调用来源
strategy 调用关系限流策略:直接、链路、关联 根据资源本身(直接)
controlBehavior 流控效果(直接拒绝/WarmUp/匀速+排队等待),不支持按调用关系限流 直接拒绝
clusterMode 是否集群限流

​ resource:资源名,即限流规则的作用对象

​ count: 限流阈值

​ grade: 限流阈值类型(QPS 或并发线程数)

​ limitApp: 流控针对的调用来源,若为 default, 则不区分调用来源

​ strategy: 调用关系限流策略

​ controlBehavior: 流量控制效果(直接拒绝、Warm Up、匀速排队)

基于QPS/并发数的流量控制

​ 流量控制主要有两种统计类型,一种是统计并发线程数,另外一种则是统计 QPS。类型由 FlowRule的 grade 字段来定义。其中,0 代表根据并发数量来限流,1 代表根据 QPS 来进行流量控制。

并发线程数控制

​ 并发数控制用于保护业务线程池不被慢调用耗尽。Sentinel 并发控制不负责创建和管理线程池,而是简单统计当前请求上下文的线程数目(正在执行的调用数目),如果超出阈值,新的请求会被立即拒绝,效果类似于信号量隔离。并发数控制通常在调用端进行配置。

QPS流量控制

​ 当 QPS 超过某个阈值的时候,则采取措施进行流量控制。流量控制的效果包括以下几种:直接拒绝Warm Up匀速排队。对应 FlowRule 中的 controlBehavior 字段。

降级规则

除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4CiEVQDn-1667384647262)(…/image/image-20221013162256575.png)]

Field 说明 默认值
resource 资源名,即规则的作用对象
grade 熔断策略,支持慢调用比例/异常比例/异常数策略 慢调用比例
count 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值
timeWindow 熔断时长,单位为 s
minRequestAmount 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入) 5
statIntervalMs 统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入) 1000ms
slowRatioThreshold 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)
**熔断策略 **
慢调用比例

​ 慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF­OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。

异常比例

异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF­OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% ­ 100%。

异常数

异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF­OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。注意:异常降级仅针对业务异常,对 Sentinel 限流降级本身的异常(BlockException)不生效。

整合openfeign进行降级

引入依赖

<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-openfeignartifactId>
dependency>

application.yml

server:
  port: 8041
spring:
  application:
    name: sentinel-openfegin
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        discovery:
          username: nacos
          password: nacos
          namespace: public
# 开启fegin对sentinel的支持          
feign:
  sentinel:
    enabled: true

openfegin接口

@FeignClient(value = "stock-nacos",path = "/stock",fallback = StackFeginServiceFallback.class)
public interface StackFeginService {
    @RequestMapping("/reduct1")
    String reduct1();
}

openfegin的fallback实现类

@Component
public class StackFeginServiceFallback implements StackFeginService{
    public String reduct1() {
        return "降级";
    }
}
热点参数限流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7MCHLhSG-1667384647262)(…/image/image-20221013164404442.png)]

controller

	@RequestMapping("/get/{id}")
    @SentinelResource(value = "getById", blockHandler = "HostBlockHandler")
    public String getById(@PathVariable("id") Integer id) throws InterruptedException {
        return "正常访问";
    }

    public String HostBlockHandler(@PathVariable("id") Integer id, BlockException e) throws InterruptedException {
        return "热点异常处理";
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7HJJt83P-1667384647263)(…/image/image-20221013164830175.png)]

Sentinel持久化模式

原始模式

如果不做任何修改,Dashboard 的推送规则方式是通过 API 将规则推送至客户端并直接更新到内存中

拉模式

pull 模式的数据源(如本地文件、RDBMS 等)一般是可写入的。使用时需要在客户端注册数据源:将对应的读数据源注册至对应的 RuleManager,将写数据源注册至 transport 的WritableDataSourceRegistry 中。

推模式

生产环境下一般更常用的是 push 模式的数据源。对于 push 模式的数据源,如远程配置中心(ZooKeeper, Nacos, Apollo等等),推送的操作不应由 Sentinel 客户端进行,而应该经控制台统一进行管理,直接进行推送,数据源仅负责获取配置中心推送的配置并更新到本地。因此推送规则正确做法应该是 配置中心控制台/Sentinel 控制台 → 配置中心 → Sentinel 数据源 → Sentinel,而不是经 Sentinel 数据源推送至配置中心。

基于Nacos配置中心控制台实现推送

引入依赖

<dependency>
    <groupId>com.alibaba.cspgroupId>
    <artifactId>sentinel-datasource-nacosartifactId>
dependency>

在nacos中配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LRPtkMOg-1667384647263)(…/image/image-20221013171141639.png)]

在yml中配置

datasource:
  flow-rule:
    nacos:
      server-addr: 127.0.0.1:8848
      username: nacos
      password: nacos
      dataId: sentinel-flow-rule
      rule-type: flow

你可能感兴趣的:(sentinel,spring,cloud,分布式)