• sentinel的原理以及基本使用


    一,Sentinel引入原因

    1,分布式系统遇到的问题

    通常情况下,一个业务逻辑往往会依赖多个服务,如一个商品展示服务会依赖商品服务,价格服务,商品评论服务等。在用户发起请求之后,在一个商品详情服务,会通过一个创建线程池,比如说里面创建100个线程,用来加载商品服务,价格服务,商品评论服务。
    在这里插入图片描述
    当用户去大量评论的时候,那么线程全部会在这个商品评论服务上面,那么会导致其他服务不可用,那么就会造成一个服务雪崩状态。

    造成服务雪崩的原因
    1,大流量请求:如在秒杀的时候,准备不充分,瞬间大量请求进来,导致服务提供者不可用
    2,硬件故障:服务器出现宕机情况
    3,出现缓存击穿:热点数据同一时间失效

    2,解决服务雪崩问题

    2.1,超时机制

    加入一个超时机制,当一个服务在一定时间内没有得到响应,就会释放资源,从而抑制资源耗尽的问题。

    2.2,服务限流

    限制请求核心服务提供者的流量,使大流量拦截在核心服务之外。可以通过线程池加队列的方式实现,队列可以是一个阻塞队列。

    2.3,服务熔断

    和现实中的断路器一样,用于监控电路情况,如果发现电路电流异常,就会跳闸,从而防止这个电路被烧毁。

    断路器的基本原理:就是说在一段时间内,如果发现失败的次数或者失败率达到一个阈值的一个情况,那么就会出现一个跳闸的情况,这个断路器就会打开,请求就会直接return返回;跳闸一段时间之后,断路器就会进入一个半开的状态,就是一个瞬时态,允许发起一次请求,如果成功,则断路器关闭,走原来的正常流程,如果不成功,那么这个断路器又会打开 ,一段时间之后又会进入一个半开的状态,如此循环下去。
    在这里插入图片描述

    2.4,服务降级

    有熔断就一定会有降级。就是当某个服务熔断之后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback(回退)回调,返回一个缺省值。或者流量前面的流量太大,后面的服务处理能力不足,会对前面的服务进行一个降级操作

    二,Sentinel工作原理

    1,什么是Sentinel

    Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。只要通过Sentinel API 定义的代码,就是资源,能够被 Sentinel保护起来

    2,sentinel控制台安装

    1,下载这个jar包,在本地跑即可。

    [ Releases · alibaba/Sentinel · GitHub ]( Releases · alibaba/Sentinel · GitHub )
    在这里插入图片描述
    2,启动jar包

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

    3,默认端口为8080,输入localhost:8080,然后登录, 默认用户名和密码都是 sentinel
    在这里插入图片描述

    4,登陆完成之后,可以看到这个sentinel的主界面。可以发现里面有大量的规则,比如说流控规则,熔断规则,热点规则,授权规则等。
    在这里插入图片描述

    3,客户端连接这个sentinel控制台

    1,需要的依赖

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        <version>2021.1</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2,yml配置文件

    spring:
      cloud:
        sentinel:
          transport:
    		#注册的地点
            dashboard: 127.0.0.1:8080
          filter:
            enabled: false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4,sentinel工作流程

    4.1,资源

    由应用程序提供的服务,比如说是一个接口,甚至是一段代码等。就是说只要被这个sentinel API定义了的代码,就是一个资源,就可以被这个sentinel保护起来。所有的资源都对应一个资源名称(resourceName),每次资源在调用时都会创建一个 Entry 对象

    4.2,规则

    就是最绕这个资源所设定的一些规则,如一些限流规则,降级规则,熔断规则等。并且所有的规则可以动态调整。

    4.3,插槽

    因此在这个资源创建的时候Entry 创建的时候,同时也会创建一系列功能插槽(slot chain),这个插槽有不同的职责。
    FlowSlot:限流
    DegradeSlot:熔断
    AuthoritySlot:授权

    4.4,工作流程

    模拟一个工作流程,对一个接口进行一个限流操作,大致流程如下,首先会定义一个资源,其次会对这个资源定义一个规则,最后会去检测这个规则是否生效。

    1,传统api的方式

    private static final String RESOURCE_NAME = "getUserMessage";
    #这个接口就是一个限流的一个对象
    @RequestMapping(value = "/getUserMessage")
    public String getPrice(){
        Entry entry = null;
        try{
            //资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
            //会将这个资源封装成一个Entry的一个对象
            entry = SphU.entry(RESOURCE_NAME);
        }catch (BlockException e1) {
            //限流异常,如果达到一个阈值,就会进入这个异常
        	return "被流控了!";
        }catch (Exception ex) {
            //正常的业务逻辑的异常捕获
            Tracer.traceEntry(ex, entry);
        } finally {
            //关闭资源
            if (entry != null) {
                entry.exit();
            }
        }
        return null;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    规则可以在容器初始化的时候就可以进行一个制定,通过这个**@PostConstruct**注解提前对这个规则进行一个初始化。

    @PostConstruct
    private static void initFlowRules(){
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule();
        //设置受保护的资源
        rule.setResource(RESOURCE_NAME);
        // 设置流控规则 QPS,每秒的请求数
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置受保护的资源阈值,每秒只能访问一次
        rule.setCount(1);
        rules.add(rule);
        // 加载配置好的规则
        FlowRuleManager.loadRules(rules);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    这样的话就简单的实现了一个限流的一个应用。同时也可以再控制台上面看到
    在这里插入图片描述

    2,注解的方式

    通过这个SentinelResource注解的的方式实现,如下,就简单实现了一个限流的一个方式。

    @RequestMapping("/info/{id}")
    @SentinelResource(value = "userinfo",
            blockHandlerClass = DefaultSentinelHandler.class, //用于流控的配置类
            blockHandler = "handleException2", //流控类里面的配置方法
            fallbackClass = DefaultFallback.class, //回调方法
            fallback = "fallback" //回调类
    )
    public R info(@PathVariable("id") Integer id){
        User user = userService.getById(id);
    
        if(id==4){
            throw new IllegalArgumentException("异常参数");
        }
    
        return R.ok().put("user", user);
    }
    //流控类里面的配置方法
    public R handleException2(@PathVariable("id") Integer id, BlockException exception){
        return R.error(-1,"===被限流降级啦===");
    }
    //回调类里面的方法
    public R fallback(@PathVariable("id") Integer id,Throwable e){
        return R.error(-1,"===被熔断降级啦==="+e.getMessage());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    也可以使用使用一个统一管理的配置类,将几种规则统一管理

    @Slf4j
    @Component
    public class MyBlockExceptionHandler implements BlockExceptionHandler {
        @Override
        public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
            log.info("BlockExceptionHandler BlockException================"+e.getRule());
            R r = null;
    
            if (e instanceof FlowException) {
                r = R.error(100,"接口限流了");
    
            } else if (e instanceof DegradeException) {
                r = R.error(101,"服务降级了");
    
            } else if (e instanceof ParamFlowException) {
                r = R.error(102,"热点参数限流了");
    
            } else if (e instanceof SystemBlockException) {
                r = R.error(103,"触发系统保护规则了");
    
            } else if (e instanceof AuthorityException) {
                r = R.error(104,"授权规则不通过");
            }
    
            //返回json数据
            response.setStatus(500);
            response.setCharacterEncoding("utf-8");
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            new ObjectMapper().writeValue(response.getWriter(), r);
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    5,规则

    5.1,流控规则

    在这里插入图片描述

    主要是通过这个应用流量的qps或者并发线程两个指标,当达到阈值的时候对这个流量进行一个控制,避免大流量的冲击,从而保证这种应用的高可用

    5.1.1,流控模式

    流控模式主要有直接模式,关联模式和这个链路模式。

    直接模式
    正常来讲都是使用这个直接模式,就是说当这个资源调用达到设置的阈值后,则会直接被流控抛出异常。

    关联模式
    当两个资源之间具有资源争抢或者依赖关系的时候,这两个资源便具有了关联。比如对数据库同一个字段的读操作和写操作存在争抢。关联的话可以设置这个关联的资源,如关联一个接口。
    在这里插入图片描述

    链路模式
    根据这个调用链路进行一个限流操作

    5.1.2,流控效果

    就是当这个qps超过某个阈值的时候,对这个流量控制采取的一系列措施。主要有快速失败,预热,匀速排队等具体实现。

    快速失败
    默认方式就是这种。就是说当这个qps达到这个阈值之后,其他新进来的请求就会立马拒绝策略,通过一个抛异常的方式实现。适用于一些压测后,了解系统水平能力的场景

    预热
    给一个缓冲时间,让流量缓慢增加,在一定时间内组件增加到这个阈值的上限,相当于给系统一个预热时间,避免系统直接被大流量压垮。

    匀速排队
    严格控制请求通过的时间,就是让这个请求匀速的通过,对应的是漏桶算法。

    5.2,熔断规则

    主要是针对链路中一些不稳定的资源进行一个熔断降级,就是暂时切断一些不稳定的调用,避免因为局部不稳定的因素导致整体服务的雪崩。
    在这里插入图片描述

    5.2.1,熔断策略

    主要有慢调用比例,异常比例,异常数等

    慢调用比例

    就是说会给这个服务的响应设置一个时间,如果外面的服务来请求的时候,该服务的响应时间大于设置的时间,则统计为一个慢调用。如果单位时间内,请求个数大于这个最小请求数,并且这个慢调用的个数或者比例超过这个阈值的时候,那么该服务就会进入到一个熔断的状态,相当于一个全开状态;一段时间后,会发起一个很小的请求,相当于一个半开状态,会去判断这个响应的时间,如果还是超过最大时间,那么又会进入全开状态,否则执行正常业务流程

    异常比例
    就是在单位时间内,请求个数大于这个最小请求数,并且这个异常的比例大于这个设置的阈值,那么就会触发这个熔断机制。

    异常数
    就是在单位时间内,请求个数大于这个最小请求数,并且这个异常个数大于这个设置的阈值,那么就会触发这个熔断机制。

    5.3,热点规则

    热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流
    在这里插入图片描述
    这个参数值只支持这个基本数据类型,并且只能通过这个@SentinelResource这个注解生效。

    5.4,系统规则

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

    5.5,授权规则

    主要是用于这个授权,增加这个黑白名单。会根据调用来源来判断该次请求是否允许放行,白名单会进行一个放行操作,黑名单不放行。
    在这里插入图片描述

    5.6,集群规则

    集群流控可以精确地控制整个集群的调用总量,结合单机限流兜底,可以更好地发挥流量控制的效果。
    适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性
    [外链图片转存中...(img-bpd1LpvL-1661579051770)]

  • 相关阅读:
    【14】c++11新特性 —>共享智能指针
    【校招VIP 前端】后台接口说明和理解
    SpringBoot 接收不到 post 请求数据与接收 post 请求数据
    ADAudit Plus:提升企业安全的不可或缺的审计解决方案
    Bean的生命周期
    天命数(c++基础)
    Go学习-基本语法(一)
    kettle如何设计数据流转逻辑
    Collection体系集合
    数据仓库与数据挖掘的第一章课后习题
  • 原文地址:https://blog.csdn.net/zhenghuishengq/article/details/126557247