Sentinel 控制台学习

引言

上篇文章已经讲过 SpringCloud Sentinel集成到微服务项目中,接下来我们继续学习怎么使用sentinel控制台对微服务进行限流,熔断,降级等一系列操作。

控制台

接下来我们单独讲解每一个菜单按钮

实时监控

实时监控: 可以看到微服务中接口的调用情况。

簇点监控

簇点监控: 展示当前微服务中,所有可用的资源,可以对这些资源进行熔断、降级、流控的相关配置,默认是将controller控制层中的接口作为资源显示出来

流控规则

流控规则:对相关的资源设置流量控制规则,一般在高并发流量的场景里面,为了降低系统宕机情况,就会限制访问流量来提高系统的稳定性。

哪些场景中,需要使用流量控制呢???

秒杀、下单、订单回流、消息型场景、API网关限流等情况

QPS流控规则

QPS流控规则: 限制每秒钟访问的请求数量。

访问/demo01接口,当1秒钟超过2个请求时候,超过的请求将返回错误信息。

当然,也可以自己在代码中通过 @SentinelResource 注解,指定流控、降级之后的回调方法

并发线程数

并发线程数规则: 当请求达到设置的最大线程数时候,在这些线程处理响应结束之前,如果此时还有线程到达,那么这个线程就会被流控。

打开两个浏览器,同时访问 /demo03 接口(注意:这个接口中写了暂停3秒的逻辑),此时第二个访问的会出现流控。

直接流控模式

直接流控模式: 直接对添加流控的资源进行流量限制,默认就是采用这种限流模式

关联流控模式

关联流控模式:两个资源之间存在关联关系,假设A资源和B资源存在关联关系,对A资源进行流控规则,关联了B资源,那么此时如果A资源满足流控规则后,就会限流B资源,这就是关联流控模式。

  • 这里模拟一下【关联流控模式】,首先由两个资源:/demo04/demo05,给/demo04添加流控规则,并且关联 /demo05 资源。
  • 使用jemeter访问 /demo05 资源,访问的过程中,浏览器单独访问 /demo04 资源,此时 /demo04 资源会发生流控。

    打开jemeter,模拟大量请求访问 /demo05 接口,之后浏览器访问 /demo04 接口,此时可以发现 /demo04 发生了流控。

注意:关联流控模式下,只有关联资源才会触发目标资源的流控规则。

链路流控模式

链路流控模式:根据接口的调用链路来实现流量控制,假设:A资源被B、C两个资源调用,也就是存在两个链路:B-->A、C-->A;那么就可以采用链路流控模式,对【B-->A】调用链路进行流控限制。

  • 这里采用 /demo06/demo07demo三个资源,其中 /demo06/demo07 都会调用demo资源。
  • 在sentinel控制台中,给【demo】资源添加流控规则,入口资源设置成 /demo06
  • 这个时候,就会对 /demo06进行限流控制
    -
    打开浏览器,多次刷新页面访问 /demo06 接口,此时会触发流控规则,而多次访问/demo07接口不会触发流控规则。

注意:sentinel默认是不会维护调用链路的,需要我们自己在application.yml 配置文件中配置

xml 复制代码
spring:
  # 配置 sentinel 控制台
  cloud:
    sentinel:
      # 让 sentinel 维护调用链路树
      web-context-unify: false
快速失败(流控效果)

快速失败:当发生流控的时候,直接快速返回失败信息。

Warm Up(流控效果)

Warm Up是【预热流控】的一种机制,所谓的预热流控,是指:当大量请求到达时候,假设一开始只处理3个请求,其他请求全部失败,之后逐渐增加处理更多的请求,例如:3个、6个、10个依次递增。sentinel默认的冷加载因子是3,它会根据【threshold / 3】开始,经过预热之后,逐渐达到阈值threshold。

使用jemeter访问/demo02接口,查看监控图如下所示。

预热流控一般适用于积分流量场景下,什么是积分流量呢???

积分流量是指:在某一段时间内可能出现大量的请求,但是过了那段时间,请求有变得平稳了,这种场景下就适用于预热流控

排队等待(流控效果)

排队等待:请求在达到设定的阈值时候,多余的请求会在指定的时间里面排队等待被处理,如果在指定时间里面,还没有被执行,那就直接失败。

使用jemeter每隔5秒钟发起10个请求访问/demo02接口,运行结束之后,查看监控界面。

从上图中就可以看出,使用【排队等待】方式就已经能够很好的解决多余请求的处理问题,而不会出现快速失败的情况。为了验证排队等待的效果,你可以设置一个快速失败的方式,再次测试接口,查看监控界面。

从上图可以看到,快速失败方式下,会出现5个接口调用成功,5个接口调用失败,并且会有一个5秒钟的时间间隔(自己设置的时间间隔),排队等待就是利用这个时间间隔,处理处于等待中的请求,从而实现流控。

熔断规则

熔断降级规则有三种,分别是:慢调用比例异常比例异常数。当触发熔断之后,不会去调用微服务接口,是否直接返回快速失败。

慢调用比例

慢调用比例:请求的响应时长超过给定的RT,并且满足【最小请求数】中满调用的占比达到阈值,则触发熔断规则。

打开jemeter,访问 /demo03 接口,此时会出发熔断规则。

异常比例

异常比例:在指定的请求数量里面,出现异常的请求达到指定比例,则触发熔断规则。

接口 /exception 模拟抛出异常即可,然后使用jemeter调用测试。

异常数

异常数:在最小请求数里面,出现异常的次数满足阈值,则发生熔断。

热点规则

热点规则:是针对接口请求中的热点参数进行流量控制,什么是热点参数呢???比如:一个查询接口中,根据商品名称查询,有:【手机】、【电脑】,假设用户大部分都查询【手机】,所以【手机】就相当于是一个热点参数,那就可以对针对这个查询参数的接口,进行流量控制。注意:热点参数规则,必须是使用 @SentinelResource 注解定义的资源。

  • 编写测试方法。
java 复制代码
@SentinelResource(value = "/api/sentinel/dashboard/parameter", blockHandler = "blockMethod")
@GetMapping("/parameter")
public String parameter(@RequestParam("id") String id, @RequestParam("name") String name) {
    System.out.println("parameter接口调用成功.id=" + id + ", name=" + name);
    return "parameter接口调用成功.id=" + id + ", name=" + name;
}

public String blockMethod(String id, String name, BlockException e) {
    return "【" + name + "】触发热点参数流控规则";
}
  • 配置热点参数规则。
  • 浏览器访问 localhost:8899/api/sentinel/dashboard/parameter?id=1&name=手机,多次刷新,此时就会触发热点参数流控规则。

    以上就是热点参数规则的配置。

系统规则

Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性

Load 自适应(仅对 Linux/Unix-like 机器生效)

系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5;

CPU usage(1.5.0+ 版本)

当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏;

平均 RT

当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒;

并发线程数

当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护;

入口 QPS

当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。

  • 配置系统规则
  • 使用jemeter压测
  • 测试结果

授权规则

很多时候,我们需要根据调用来源来判断该次请求是否允许放行,这时候可以使用 Sentinel 的来源访问控制(黑白名单控制)的功能。

来源访问控制根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过

来源访问控制规则(AuthorityRule)非常简单,主要有以下配置项:

  • resource:资源名,即限流规则的作用对象。
  • limitApp:对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB。
  • strategy :限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式。
    配置授权规则:
  • 代码编写
    实现com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser接口,在parseOrigin方法中区分来源,并交给spring管理
    注意:如果引入CommonFilter,此处会多出一个
java 复制代码
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Component
public class MyRequestOriginParser implements RequestOriginParser {
    /**
     * 通过request获取来源标识,交给授权规则进行匹配
     * @param request
     * @return
     */
    @Override
    public String parseOrigin(HttpServletRequest request) {
        // 标识字段名称可以自定义
        String origin = request.getParameter("serviceName");
//        if (StringUtil.isBlank(origin)){
//            throw new IllegalArgumentException("serviceName参数未指定");
//        }
        return origin;
    }
}
  • 测试:origin是order的请求不通过。

集群流控

集群流程官方文档

为什么要使用集群流控呢?假设我们希望给某个用户限制调用某个 API 的总 QPS 为 50,但机器数可能很多(比如有 100 台)。这时候我们很自然地就想到,找一个 server 来专门来统计总的调用量,其它的实例都与这台 server 通信来判断是否可以调用。这就是最基础的集群流控的方式。

另外集群流控还可以解决流量不均匀导致总体限流效果不佳的问题。假设集群中有 10 台机器,我们给每台机器设置单机限流阈值为 10 QPS,理想情况下整个集群的限流阈值就为 100 QPS。不过实际情况下流量到每台机器可能会不均匀,会导致总量没有到的情况下某些机器就开始限流。因此仅靠单机维度去限制的话会无法精确地限制总体流量。而集群流控可以精确地控制整个集群的调用总量,结合单机限流兜底,可以更好地发挥流量控制的效果

集群流控中共有两种身份:

  • Token Client:集群流控客户端,用于向所属 Token Server 通信请求token。集群限流服务端会返回给客户端结果,决定是否限流
  • Token Server :即集群流控服务端,处理来自 Token Client 的请求,根据配置的集群规则
    判断是否应该发放 token(是否允许通过)

Sentinel 集群流控支持限流规则和热点规则两种规则,并支持两种形式的阈值计算方式:

  • 集群总体模式即限制整个集群内的某个资源的总体 qps 不超过此阈值
  • 单机均摊模式单机均摊模式下配置的阈值等同于单机能够承受的限额,token server 会根据连接数来计算总的阈值(比如独立模式下有 3个 client 连接到了 token server,然后配的单机均摊阈值为 10,则计算出的集群总量就为30),按照计算出的总的阈值来进行限制。这种方式根据当前的连接数实时计算总的阈值,对于机器经常进行变更的环境非常适合
启动方式

Sentinel 集群限流服务端有两种启动方式:

  • 独立模式(Alone) ,即作为独立的 token server 进程启动,独立部署,隔离性好 ,但是需要额外的部署操作。独立模式适合作为 Global Rate Limiter 给集群提供流控服务
  • 嵌入模式(Embedded) ,即作为内置的 token server 与服务在同一进程中启动。在此模式下,集群中各个实例都是对等的,token server 和 client 可以随时进行转变,因此无需单独部署,灵活性比较好。但是隔离性不佳 ,需要限制 token server 的总QPS,防止影响应用本身。嵌入模式适合某个应用集群内部的流控

    云上版本 AHAS Sentinel 提供开箱即用的全自动托管集群流控能力,无需手动指定/分配 token server 以及管理连接状态,同时支持分钟小时级别流控、大流量低延时场景流控场景,同时支持 Istio/Envoy 场景的 Mesh 流控能力

扩展知识点

统一异常处理BlockException

自定义BlockException异常处理,可以针对不同的异常情况,响应不同的结果,当然你也可以不使用统一的异常处理,那就是需要在每一个方法中使用 @SentinelResource 注解定义异常处理方法。

java 复制代码
package com.gitcode.demo.exception;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;

/**
 * @version 1.0.0
 * @Date: 2023/4/25 20:32
 * @Copyright (C) ZhuYouBin
 * @Description: 统一异常处理【BlockException】
 */
@Component
public class CustomBlockExceptionHandler implements BlockExceptionHandler {

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        // TODO 在这里就可以自定义返回响应数据
        String msg = "";
        if (e instanceof FlowException) {
            msg = "流控异常";
        } else if (e instanceof DegradeException) {
            msg = "服务降级异常";
        } else if (e instanceof ParamFlowException) {
            msg = "热点参数流控异常";
        } else if (e instanceof SystemBlockException) {
            msg = "触发系统保护规则异常";
        } else if (e instanceof AuthorityException) {
            msg = "授权规则不通过异常";
        }
        // 响应结果
        response.setStatus(500);
        response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        // 返回JSON数据
        new ObjectMapper().writeValue(response.getWriter(), msg);
    }

}

到此,Sentinel控制台配置相关规则就介绍完啦。

相关推荐
无敌最俊朗@1 小时前
stm32学习之路——八种GPIO口工作模式
c语言·stm32·单片机·学习
EterNity_TiMe_2 小时前
【论文复现】STM32设计的物联网智能鱼缸
stm32·单片机·嵌入式硬件·物联网·学习·性能优化
L_cl2 小时前
Python学习从0到1 day28 Python 高阶技巧 ⑤ 多线程
学习
前端SkyRain2 小时前
后端Node学习项目-用户管理-增删改查
后端·学习·node.js
提笔惊蚂蚁2 小时前
结构化(经典)软件开发方法: 需求分析阶段+设计阶段
后端·学习·需求分析
DDDiccc2 小时前
JAVA学习日记(十五) 数据结构
数据结构·学习
腾科张老师4 小时前
为什么要使用Ansible实现Linux管理自动化?
linux·网络·学习·自动化·ansible
tao_sc6 小时前
luckfox-pico-max学习记录
学习
zx_zx_1236 小时前
多态的学习
c++·学习
B1nna9 小时前
SpringMVC学习记录(三)之响应数据
java·学习·json·springmvc·jsp