美文网首页
java Sentinel

java Sentinel

作者: 小和大大 | 来源:发表于2023-03-05 17:09 被阅读0次

    (一)、sentinel介绍
    1、sentinel是什么?

    随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。
    源码地址:https://github.com/alibaba/Sentinel
    官方文档:https://github.com/alibaba/Sentinel/wiki

    2、Sentinel具有以下特征:

    丰富的应用场景: Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、实时熔断下游不可用应用等。
    完备的实时监控: Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
    广泛的开源生态: Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
    完善的 SPI 扩展点: Sentinel 提供简单易用、完善的 SPI 扩展点。您可以通过实现扩展点,快速的定制逻辑。例如定制规则管理、适配数据源等。
    阿里云提供了 企业级的 Sentinel 服务,应用高可用服务 AHAS

    Sentinel和Hystrix对比

    8592a60ed27d49aca54b772172405683.png

    3、sentinel能解决什么问题

    【大流量请求】:在秒杀和大促开始前,如果准备不充分,瞬间大量请求会造成服务提供者的不可用。
    【硬件故障】:可能为硬件损坏造成的服务器主机宕机, 网络硬件故障造成的服务提供者的不可访问。
    【缓存击穿】:一般发生在缓存应用重启, 缓存失效时高并发,所有缓存被清空时,以及短时间内大量缓存失效时。大量的缓存不命中, 使请求直击后端,造成服务提供者超负荷运行,引起服务不可用。

    在服务提供者不可用的时候,会出现大量重试的情况:用户重试、代码逻辑重试,这些重试最终导致:进一步加大请求流量。所以归根结底导致雪崩效应的最根本原因是:大量请求线程同步等待造成的资源耗尽。当服务调用者使用同步调用时, 会产生大量的等待线程占用系统资源。一旦线程资源被耗尽,服务调用者提供的服务也将处于不可用状态, 于是服务雪崩效应产生了。

    服务雪崩效应:因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程,就叫服务雪崩效应

    4、重要概念

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

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

    工作主流程
    在 Sentinel 里面,所有的资源都对应一个资源名称(resourceName),每次资源调用都会创建一个 Entry 对象。Entry 可以通过对主流框架的适配自动创建,也可以通过注解的方式或调用 SphU API 显式创建。Entry 创建的时候,同时也会创建一系列功能插槽(slot chain),这些插槽有不同的职责,例如:
    NodeSelectorSlot 负责收集资源的路径,并将这些资源的调用路径,以树状结构存储起来,用于根据调用路径来限流降级;
    ClusterBuilderSlot 则用于存储资源的统计信息以及调用者信息,例如该资源的 RT, QPS, thread count 等等,这些信息将用作为多维度限流,降级的依据;
    StatisticSlot 则用于记录、统计不同纬度的 runtime 指标监控信息;
    FlowSlot 则用于根据预设的限流规则以及前面 slot 统计的状态,来进行流量控制;
    AuthoritySlot 则根据配置的黑白名单和调用来源信息,来做黑白名单控制;
    DegradeSlot 则通过统计信息以及预设的规则,来做熔断降级;
    SystemSlot 则通过系统的状态,例如 load1 等,来控制总的入口流量;

    详细的介绍请参考sentinel官方文档:sentinel中文文档

    (二)、sentinel的使用
    一、定义资源和规则
    1、引入依赖

    <!-- sentinel核心包-->
            <dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-core</artifactId>
                <version>${sentinel.versioin}</version>
            </dependency>
    

    2、定义规则
    规则的种类:Sentinel 支持以下几种规则:流量控制规则、熔断降级规则、系统保护规则、来源访问控制规则 和 热点参数规则。
    以流控规则为例,在资源保护前先定义好流控规则,所以使用到 @PostConstruct注解,在该bean对象实例化之前将定义的流控规则加载完成。

    /**
         * 设置流控规则
         */
        @PostConstruct
        public static void initFlowRules() {
            List<FlowRule> flowRules = new ArrayList<>();
            FlowRule flowRule = new FlowRule();
            // 设置受保护的资源
            flowRule.setResource(RESOURCE_NAME);
            // 设置流控规则 QPS
            flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
            // 设置受保护的资源阈值
            // Set limit QPS to 20.
            flowRule.setCount(1);
            flowRules.add(flowRule);
            // 加载配置好的规则
            FlowRuleManager.loadRules(flowRules);
        }
    

    3、编写资源保护的代码

    @RestController
    @Slf4j
    public class HelloController {
        private static final String RESOURCE_NAME = "hello";
    
        @RequestMapping(value = "/hello")
        public String hello() {
            Entry entry = null;
            try {
                entry = SphU.entry(RESOURCE_NAME);
                // 被保护的业务逻辑
                String str = "hello world";
                log.info("====="+str);
                return str;
            } catch (BlockException ex) {
                // 资源访问阻止,被限流或被降级
                //进行相应的处理操作
                log.info("block!");
            } catch (Exception ex) {
                // 若需要配置降级规则,需要通过这种方式记录业务异常
                Tracer.traceEntry(ex, entry);
            } finally {
                if (entry != null) {
                    entry.exit();
                }
            }
            return null;
        }
    
        /**
         * 设置流控规则
         */
        @PostConstruct
        public static void initFlowRules() {
            List<FlowRule> flowRules = new ArrayList<>();
            FlowRule flowRule = new FlowRule();
            // 设置受保护的资源
            flowRule.setResource(RESOURCE_NAME);
            // 设置流控规则 QPS
            flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
            // 设置受保护的资源阈值
            // Set limit QPS to 20.
            flowRule.setCount(1);
            flowRules.add(flowRule);
            // 加载配置好的规则
            FlowRuleManager.loadRules(flowRules);
        }
    }
    

    资源保护的核心代码块:

    // 1.5.0 版本开始可以利用 try-with-resources 特性(使用有限制)
    // 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
    try (Entry entry = SphU.entry("resourceName")) {
      // 被保护的业务逻辑
      // do something here...
    } catch (BlockException ex) {
      // 资源访问阻止,被限流或被降级
      // 在此处进行相应的处理操作
    }
    

    测试效果:

    其他规则定义和资源保护的详细介绍可以参考官方文档:如何使用

    以上方式定义资源的缺点很明显

    业务侵入性很强,定义资源保护需要在controller中写入非业务代码.
    规则配置不灵活,若需要添加新的保护规则,还需要手动添加
    二、@SentinelResource注解+Sentinel dashboard控制台
    Sentinel 支持通过 @SentinelResource 注解定义资源并配置 blockHandler 和 fallback 函数来进行限流之后的处理。
    同时支持通过Sentinel控制台定义规则,可以简化开发。

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

    1、使用该注解需要引入依赖:

    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-annotation-aspectj</artifactId>
        <version>1.8.0</version>
    </dependency>
    

    如果是spring项目需要配置切面支持(springboot项目会自动配置,不用关注)

    @Configuration
    public class SentinelAspectConfiguration {
    
        @Bean
        public SentinelResourceAspect sentinelResourceAspect() {
            return new SentinelResourceAspect();
        }
    }
    

    2、使用@SentinelResource定义资源

    // 原本的业务方法.
    @SentinelResource(value = "findOrderByUserId",
                    blockHandler = "handleException", // 指定触发限流等规则时执行的方法名
                    fallback = "fallback" // 指定fallback降级执行的方法名
                    //blockHandlerClass = ExceptionUtil.class, // 指定blockHandler函数的所在类,如果在当前类可以忽略
                    //fallbackClass = ExceptionUtil.class,  指定fallback函数所在类,如果在当前类可以忽略
                      )
    @RequestMapping(value = "/user/findOrderByUserId/{id}")
    public User findOrderByUserId(@PathVariable("id") Integer id) {
        throw new RuntimeException("getUserById command failed");
    }
    
    // blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用
    public User handleException(@PathVariable("id") Integer id, BlockException ex) {
        return new User("admin");
    }
    
    // fallback 函数,原方法调用被降级的时候调用
    public User fallback(@PathVariable("id") Integer id, Throwable e) {
        return new User("admin1"); 
    }
    

    使用@SentinelResource需要注意:
    配置了@SentinelResource注解的方法都视作资源,可以配置在@RequestMapping("/user/findOrderByUserId/{id}")修饰的接口层,也可以配置在service层,如果配置在了接口上,则sentinel会产生两套资源链路,一个是@RequestMapping中的value属性的"/user/findOrderByUserId/{id}"链路,一个是@SentinelResource(“findOrderByUserId”)配置的"findOrderByUserId"链路
    (1)如果这两个链路都配置了规则的话,默认会先执行接口产生的链路;
    (2)如果没有为接口配置规则,就会执行@SentinelResource的资源链路。

    55d529fddda442b187da15099f400f33.png

    3、编写ExceptionUtil,注意如果指定了fallback函数或者blockHandler的class类,该类中的方法必须是static方法

    public class ExceptionUtil {
    
        public static R handleException(Integer id, BlockException e){
            log.error("===被限流啦===");
            return new User("admin");
        }
        
        public static  fallback(Integer id,Throwable e){
            log.error("===被异常降级啦===");
            return new User("admin1");
        }
    }
    
    

    4、客户端接入Sentinel dashboard控制台

    客户端需要引入 Transport 模块来与 Sentinel 控制台进行通信。

    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-transport-simple-http</artifactId>
        <version>1.8.0</version>
    </dependency>
    

    配置启动参数
    启动时加入 JVM 参数 -Dcsp.sentinel.dashboard.server=consoleIp:port 指定控制台地址和端口。若启动多个应用,则需要通过 -Dcsp.sentinel.api.port=xxxx 指定客户端监控 API 的端口(默认是 8719)。
    除了修改 JVM 参数,也可以通过配置文件取得同样的效果。更详细的信息可以参考 启动配置项。

    启动 Sentinel 控制台
    您可以从 release 页面 下载最新版本的控制台 jar 包。
    下载控制台 jar 包并在本地启动:可以参见 此处文档

    #启动控制台命令
    java -jar sentinel-dashboard-1.8.0.jar
    

    用户可以通过如下参数进行配置:
    -Dsentinel.dashboard.auth.username=sentinel 用于指定控制台的登录用户名为 sentinel;
    -Dsentinel.dashboard.auth.password=123456 用于指定控制台的登录密码为 123456;如果省略这两个参数,默认用户和密码均为 sentinel;
    -Dserver.servlet.session.timeout=7200 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟;
    访问http://localhost:8080/#/login ,默认用户名密码: sentinel/sentinel

    触发客户端初始化
    Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包,所以要确保客户端有访问量;
    三、Spring Cloud Alibaba整合Sentinel
    1.引入依赖

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    

    2.添加yml配置,为微服务设置sentinel控制台地址
    添加Sentinel后,需要暴露/actuator/sentinel端点,而Springboot默认是没有暴露该端点的,所以需要设置,测试http://localhost:8800/actuator/sentinel

    server:
      port: 8800
    
    spring:
      application:
        name: sentinel-demo
      cloud:
        sentinel:
          transport:
            # 添加sentinel的控制台地址
            dashboard: 127.0.0.1:8080
            # 指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer
            # port: 8719
        
    #暴露actuator端点   
    management:
      endpoints:
        web:
          exposure:
            include: '*'
    
    

    3.在sentinel控制台中设置流控规则
    资源名: 接口的API
    针对来源: 默认是default,当多个微服务都调用这个资源时,可以配置微服务名来对指定的微服务设置阈值
    阈值类型: 分为QPS和线程数 假设阈值为10
    QPS类型: 只得是每秒访问接口的次数>10就进行限流
    线程数: 为接受请求该资源分配的线程数>10就进行限流

    661f95d570f640ccb4c7e43ac4672904.png

    测试: 因为QPS是1,所以1秒内多次访问会出现如下情形:

    4d71b0ada99e428da541cc1a35453f55.png

    微服务和Sentinel Dashboard通信原理
    Sentinel控制台与微服务端之间,实现了一套服务发现机制,集成了Sentinel的微服务都会将元数据传递给Sentinel控制台,架构图如下所示:

    99569db8801545db9c3f9ab77d30db63.png

    ————————————————
    原文链接:https://blog.csdn.net/weixin_43868443/article/details/119702942

    相关文章

      网友评论

          本文标题:java Sentinel

          本文链接:https://www.haomeiwen.com/subject/yufpldtx.html