【限流与Sentinel超详细分析】

Sentinel

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来保障微服务的稳定性。

1 Sentinel 基本概念

资源 (Resource):

  • 资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码;
  • 只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,服务名称作为资源名来标示资源。

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

2 Sentinel核心功能

2.1 流量控制

任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。Sentinel 作为一个调配器,可以根据需要把随机的请求进行整型,如下图所示

在这里插入图片描述

流量控制主要有如下三个角度:

  • 限流指标,例如QPS,并发线程数等指标
  • 限流策略,例如直接限流(根据自己的指标来限流,关联限流(根据有关联关系的其他资源来限流),调用链路限流(根据指定路调用链路涌入的的流量来限流)
  • 限流效果,触发限流以后的请求该如何处理, 例如快速失败(fast fail),慢启动(warm up), 排队等待

2.2 熔断降级

除了流量控制以外,对调用链路中的不稳定资源进行处理, 保护整个调用链路, 也是 Sentinel 的作用之一。

2.2.1 熔断

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

在服务内调用其它服务时, 比如基于 RestTemplate 进行调用时, 是同步式的调用, 发起调用的服务在被调用的服务返回前, 不能去做别的事情;

如果下游服务出现故障, 迟迟无法返回, 那么上游服务就被阻塞在调用下游服务的位置

随着新的请求不断到来, 将有越来越多的上游服务线程被阻塞在调用故障服务的位置, 进而使上游服务没有线程可用, 最终使上游服务也发生故障,

以此类推, 导致整个调用链路中的服务都不可用, 造成雪崩;

预防雪崩问题有以下几个方法:

  1. 超时时间: 设定超时时间, 请求超过一定时间没有响应, 就立即返回一个错误状态, 不会无休止等待;

    缺点是仍然会有请求到达故障, 并且数量没有限制, 服务器的线程被阻塞直到超时时间才被释放;

  2. 线程隔离: 遵循仓壁模式, 对当前服务的不同API, 设置其所能占用的并发线程数量的上限, 这样, 即使当前 API 内调用了某个故障的下游服务, 也不会耗尽当前服务的所有线程资源;

    sentinel中, 配置限流规则时, 设置最大线程数, 就有线程隔离的作用;
    缺点是仍然有一定数量的请求可以到达故障服务;

  3. 熔断机制: 根据响应时间, 错误响应比例等依据, 对故障业务进行熔断, 拦截访问该业务的请求; 对这些请求, 也不能置之不理, 比如我可以对这些请求进行降级处理;

2.2.2 降级

服务调用无法正常完成时, 例如被限流, 超时, 或者出现异常, 或者服务被熔断等后, 最好是我不能把请求扔在那不管, 对到来的请求, 可以执行一个替代的简化的处理逻辑, 这就是降级;

2.3 熔断和降级辨析

目的上来说, 熔断和降级, 都是为了提高系统的可用性, 都是为了防止系统崩溃;

熔断的侧重点是防止服务雪崩, 阻止对故障服务的调用, 防止因为调用故障服务导致当前服务资源耗尽,保护上游服务的稳定性。

降级侧重点是在服务出现问题时或者 QPS 过大时取消问题服务或者边缘服务的完整业务, 转而提供基本的服务。比如服务被熔断时, 就可以使用降级; 比如电商平台大促期间, 就可以对边缘业务进行降级处理;

熔断的时候, 可以配合降级机制, 阻止对故障服务调用的同时, 提供保底的基本的服务; 但降级一般不会触发熔断机制;

3 Sentinel的使用

Sentinel 可以分为 Sentinel 核心库和 Dashboard。核心库不依赖 Dashboard,但是结合 Dashboard 可以取得最好的效果。

使用 Dashboard 只需要下载 jar 包Releases · alibaba/Sentinel (github.com), 并通过命令行启动; 网页访问时, 默认用户名和密码都是 sentinel

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.3.jar

使用核心库, 需要导包

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

在服务中进行配置

spring:
  cloud:
    sentinel:
      transport:
        # 指定操作面板的地址
        dashboard: localhost:8080

3.1 定义资源

定义资源的方式有多种,其中比较常用是注解方式定义,框架自适配定义。

  • 框架自适配

    为了减少开发的复杂程度,Sentinel 对大部分的主流框架,例如 Web Servlet、Dubbo、Spring Cloud等都做了适配

    例如使用SpringMVC时, 一个请求的应用内路径就会被自动识别为资源;

  • 注解方式定义资源

    Sentinel 支持通过 @SentinelResource 注解定义资源并配置 blockHandlerfallback 函数来进行降级处理。示例:

    // 使用注解声明资源时, 一定要指定blockHandler, 并blockHandler一定要是public的
    // 否则触发限流时, 直接服务器内部错误500; 而自动识别的资源, 会自动输出
    // Blocked by Sentinel (flow limiting)
    @SentinelResource(blockHandler = "blockHandlerForGetUser")
    public User getUserById(String id) {
         
    	//......
    }
    
    // blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用
    public User blockHandlerForGetUser(String id, BlockException ex) {
         
        return new User("admin");
    }
    

3.2 定义规则

Sentinel 的所有规则都可以在内存中动态地查询及修改,修改之后立即生效; 规则可以分为流控规则, 熔断规则, 热点规则, 授权规则等;

推荐使用 Dashboard 去定义规则;

4 流控规则

顾名思义, 用于流量控制的规则; 同一个资源可以对应多条限流规则。Sentinel 会对该资源的所有限流规则依次遍历,直到有规则触发限流或者所有规则遍历完毕。

阈值类型

主要有两种统计类型,一种是统计线程数,另外一种则是统计 QPS; 其中线程数、QPS 值,都是 Sentinel 实时统计获取的。

  • 线程数限流用于保护服务器线程数不被耗尽, 可以防止雪崩。
  • 基于QPS的限流,直接限制同时处理请求的数量。当 QPS 超过某个阈值的时候,则采取措施进行流量控制;

流控模式

直接限流

即最直接的方式,根据被访问资源本身的流量,决定是否要限流;

关联流量限流

当两个资源之间具有资源争抢或者依赖关系的时候,这两个资源便具有了关联。

比如不同的 Sentinel Resource 对数据库同一个字段进行写操作,如果放任这两个 Sentinel Resource 争抢数据库资源,则争抢本身带来的开销会降低整体的吞吐量。

可使用关联限流来避免具有关联关系的资源之间过度的争抢,举例来说

  • read_dbwrite_db 这两个资源分别代表数据库读写;
  • 我们可以给 read_db 设置限流规则来达到写优先的目的:设置限流策略为关联流量限流, 同时设置关联资源为write_db
  • 这样当写库操作过于频繁时,读数据的请求会被限流。

链路限流

在高版本 Sentinel中, 已经不支持链路限流;

sentinel中记录了资源之间的调用链路,这些资源通过调用关系,相互之间构成一棵调用树。这棵树的根节点是一个名字为 machine-root 的虚拟节点,调用链的入口都是这个虚节点的子节点。

                  machine-root
                    /       \
                   /         \
             Entrance1     Entrance2
                /             \
               /               \
      DefaultNode(nodeA)   DefaultNode(nodeA)

上图中来自入口 Entrance1Entrance2 的请求都调用到了资源 NodeA,Sentinel 允许只根据某个入口的统计信息对资源限流。比如我们可以设置 限流策略为 链路限流,同时设置 访问入口为 Entrance1 来表示只有从入口 Entrance1 的调用才会记录到 NodeA 的限流统计当中,而对来自 Entrance2 的调用漠不关心。

流控效果

只有在阈值类型为QPS的时候, 才能设置流控效果;

快速失败

该方式是默认的流量控制方式,当QPS超过阈值后,新的请求就会被立即拒绝,拒绝方式为直接抛出 FlowException, FlowExceptionBlockException 的子类;

慢启动

系统启动时, 不能上来就把流量拉到系统稳定运行时能承受的最大QPS, 多种原因:

  • 这时候各级缓存还没有

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值