ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Sentinel分布式系统的流量组件

2021-10-14 12:32:23  阅读:135  来源: 互联网

标签:规则 组件 限流 分布式系统 Sentinel sentinel public 资源


Sentinel分布式系统的流量组件

Sentinel是阿里开源的项目,提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。

官网:https://github.com/alibaba/Sentinel/wiki

1、主要特性

在这里插入图片描述

2、开源生态

在这里插入图片描述

3、Sentinel的基本概念

资源

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

规则

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

4、Sentinel的功能和设计理念

流量控制

流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。然而,从系统稳定性角度考
虑,在处理请求的速度上,也有非常多的讲究。任意时间到来的请求往往是随机不可控的,而系统的处
理能力是有限的。我们需要根据系统的处理能力对流量进行控制。Sentinel 作为一个调配器,可以根据 需要把随机的请求调整成合适的形状

流量控制有以下几个角度:

资源的调用关系,例如资源的调用链路,资源和资源之间的关系; 运行指标,例如 QPS、线程池、系统负载等;
控制的效果,例如直接限流、冷启动、排队等。 Sentinel 的设计理念是让您自由选择控制的角度,并进行灵活组合,从而达到想要的效果。

熔断降级

除了流量控制以外,及时对调用链路中的不稳定因素进行熔断也是 Sentinel 的使命之一。由于调用关系
的复杂性,如果调用链路中的某个资源出现了不稳定,可能会导致请求发生堆积,进而导致级联错误。

在限制的手段上:

Sentinel 对这个问题采取了两种手段:
通过并发线程数进行限制
和资源池隔离的方法不同,Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影
响。这样不但没有线程切换的损耗,也不需要您预先分配线程池的大小。当某个资源出现不稳定的情况
下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源上堆积
到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。
通过响应时间对资源进行降级
除了对并发线程数进行控制以外,Sentinel 还可以通过响应时间来快速降级不稳定的资源。当依赖的资
源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢
复。

Sentinel 同时提供系统维度的自适应保护能力。防止雪崩,是系统防护中重要的一环。
Sentinel 的主要工作机制如下:

对主流框架提供适配或者显示的 API,来定义需要保护的资源,并提供设施对资源进行实时统计和 调用链路分析。
根据预设的规则,结合对资源的实时统计信息,对流量进行控制。同时,Sentinel 提供开放的接 口,方便您定义及改变规则。 Sentinel
提供实时的监控系统,方便您快速了解目前系统的状态。

Sentinel HelloWorld实现

1、创建父级maven空项目,-----sentineltest
导入依赖:

 <modules>
        <module>sentinel-springcloud</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.bdqn</groupId>
    <artifactId>sentineltest</artifactId>
    <packaging>pom</packaging>  //记得这里需要加packaging标签 父类型都为pom类型
    <version>0.0.1-SNAPSHOT</version>
    <name>sentineltest</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <spring-cloud.version>2020.0.4</spring-cloud.version>
        <springboot.version>2.5.5</springboot.version>
        <springcloudalibaba.version>2021.1</springcloudalibaba.version>
    </properties>
    <dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${springboot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>${springcloudalibaba.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
    </dependencyManagement>

2、创建新模块---- sentinel-helloworld
导入依赖:

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

2、application.yml配置文件:

server:
  port: 8082
  servlet:
    context-path: /
spring:
  application:
    name: sentinel-helloWorld
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080

新建启动类SentinelHelloworldApplication :

@SpringBootApplication
@EnableAsync  //支持异步调用
public class SentinelHelloworldApplication {
    public static void main(String[] args) {
        SpringApplication.run(SentinelHelloworldApplication.class, args);
    }
}

3、controller层新建SentinelHelloWorld:定义规则和使用限流规则

/**
 * @author 江江江
 * @create 2021/10/12 15:00
 */
@RestController
public class SentinelHelloWorld {
    /**
     * 定义限流规则
     * PostConstruct 构造方法执行完执行方法 定义和加载限流规则
     */
    @PostConstruct
    public void initFlowRules(){
        List<FlowRule> rules=new ArrayList<>(); //定义限流规则集合
        FlowRule rule=new FlowRule();  //定义限流规则
        rule.setResource("helloworld");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS); //定义限流规则类型
        rule.setCount(2); //定义QPS阙值 每秒最多通过的请求个数
        rules.add(rule); //添加规则到集合
        FlowRuleManager.loadRules(rules);  //加载规则集合
    }
}

4、测试:
在这里插入图片描述

Sentinel dashboard控制台搭建

Sentinel 控制台是流量控制、熔断降级规则统一配置和管理的入口,它为用户提供了机器自发现、簇点
链路自发现、监控、规则配置等功能。在 Sentinel 控制台上,我们可以配置规则并实时查看流量控制效
果。

1、下载sentinel-dashboard-1.8.1.jar

https://github.com/alibaba/Sentinel/releases/download/1.8.1/sentinel-dashboard-1.8.1.jar

2、启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本。
在这里插入图片描述

java -jar sentinel-dashboard-1.8.2.jar

也可以使用这个命令

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

3、http://localhost:8080/ 访问 用户名和密码都是 sentinel
在这里插入图片描述
4、客户端sentinel-helloworld模块
创建AspectJ 配置类

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

controller层SentinelHelloWorld

@RestController
public class SentinelHelloWorld {
    @Resource
    private AsyncService asyncService;
    @RequestMapping("helloworld")
    public String helloWorld(){
        try(Entry entry= SphU.entry("HelloWorld")){ //使用限流围观 HelloWorld
            return "Sentinel 你好!"+System.currentTimeMillis();
        } catch (Exception e) {
            e.printStackTrace();
            return "系统繁忙,请稍后!";  //降级处理
        }
    }
    /**
     * 返回值布尔值定义资源
     * @return
     */
    @RequestMapping("helloWorld2")
    public String helloWorld2(){
        //资源名称可使用任意业务语文的字符串
        if(SphO.entry("HelloWorld2")){
            //务必保证finally会被执行
            try {
                /**
                 * 被保护的业务逻辑
                 */
                return "Sentinel2 你好!"+System.currentTimeMillis();
            }finally {
                SphO.exit();
            }
        }else {
            //资源访问阻止 被限流或被降级
            //进行相应的处理操作
            return "系统繁忙,请稍后!"; //降级处理
        }
    }
    /**
     * 注解方式定义资源
     * @return
     */
    @SentinelResource(value = "helloWorld3",blockHandler = "blockHandlerForHelloWorld3")
    @RequestMapping("helloWorld3")
    public String helloWorld3(){
        return "Sentinel3 你好!by 注解方法@SentinelResource"+System.currentTimeMillis();
    }
    /**
     * 原方法调用被限流、降级、系统保护的时候调用
     * @param ex
     * @return
     */
    public String blockHandlerForHelloWorld3(BlockException ex){
        ex.printStackTrace();
        return "系统繁忙,请稍后!";
    }
    /**
     * 异步支持
     */
    @RequestMapping("helloWorld4")
    public void helloWorld4(){
        AsyncEntry asyncEntry=null;
        try {
            asyncEntry =SphU.asyncEntry("helloWorld4");
            asyncService.doSomethingAsync();
        }catch (BlockException e){
            System.out.println("系统繁忙,请稍后!");
        }finally {
            if(asyncEntry!=null){
                asyncEntry.exit();
            }
        }
    }
    }

5、创建AsyncService异步调用类以及方法

@Service
public class AsyncService {
    @Async
    public void doSomethingAsync(){
        System.out.println("async start....");
        try {
            Thread.sleep(400);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("async end....");
    }
}

6、新建sentinel-springcloud模块
导入依赖:
sentinel整合nacos实现配置持久化

<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2021.1</version>
        </dependency>
        <--sentinel整合nacos实现配置持久化--!>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

配置application.yml文件

server:
  port: 8082
  servlet:
    context-path: /
spring:
  application:
    name: sentinel-springcloud  #设置应用名称
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080  #设置sentinel连接控制台的主机地址和端口
      datasource:
        ds:
          nacos:
            server-addr: localhost:8848 #nacos连接地址
            group-id: DEFAULT_GROUP #nacos连接的分组
            rule-type: flow #流控规则 rule-type配置表示该数据中的规则属于那种类型的规则(flow,degrade,authority,system, param-flow, gw-flow, gw-api-group)
            data-id: java1234_sentinel # 读取配置文件的 data-id
            data-type: json # 读取培训文件类型为json

controller层SentinelHelloWorld 类

@RestController
public class SentinelHelloWorld {
    /**
     * 注解方式定义资源
     * @return
     */
    @SentinelResource(value = "helloWorld_springcloud",blockHandler = "blockHandlerForHelloWorld3")
    @RequestMapping("helloWorld3")
    public String helloWorld3(){
        return "Sentinel3 你好!by 注解方法@SentinelResource"+System.currentTimeMillis();
    }
    /**
     * 原方法调用被限流、降级、系统保护的时候调用
     * @param ex
     * @return
     */
    public String blockHandlerForHelloWorld3(BlockException ex){
        ex.printStackTrace();
        return "系统繁忙,请稍后!";
    }
}

6、测试成功
在这里插入图片描述
进入sentinel控制台即可实时监控、以及进行编辑

流量控制(flow control),其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时
对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。

限流类型分为:
QPS: 每秒请求数限制
线程数: 资源使用线程数限制
流控模式
直接: 资源直接限流,这个就是简单的限流。
关联: 关联模式需要填写关联资源的路径,意为如果关联资源的流量超额之后,限流自己(自己为资
源名填写的路径)。
链路: 如果是链路模式需要填写入口资源,限制入口资源对自己的调用。
流控效果
快速失败: (Ruleconstant.CONTROL_BEHAVIOR_DEFAULT)方式是默认的流量控制方式,当QPS超过
任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出F1owException。这种方式适用于对系
统处理能力确切已知的情况下,比如通过压测确定了系统的准确水位时。
Warm Up: (RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。当系统长期
处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启
动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系
统被压垮。
排队等待: (RuleConstant.cONTROL_BEHAV工OR_RATE_LIMITER)方式会严格控制请求通过的间隔时
间,也即是让请求以均匀的速度通过,对应的是漏桶算法。
同一个资源可以同时有多个限流规则,检查规则时会依次检查。

![在这里插入图片描述](https://www.icode9.com/i/ll/?i=b5d0365671b6418a88eaf4d32d2fc420.png?,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5oOz5ZCD57Gz6LGG6IWQ,size_20,color_FFFFFF,t_70,g_se,x_16
熔断规则
需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,
避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配
置。

在这里插入图片描述
启动sentinel-springcloud项目,发现sentinel控制台读取到了nacos里的配置,频繁刷新也能流控;

标签:规则,组件,限流,分布式系统,Sentinel,sentinel,public,资源
来源: https://blog.csdn.net/weixin_50823456/article/details/120747411

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有