Spring Cloud Alibaba-Sentinel服务熔断组件学习

Spring Cloud Alibaba-Sentinel服务熔断组件学习

前言

Spring Cloud Alibaba-Sentinel服务熔断组件学习

提示:以下是本篇文章正文内容,下面案例可供参考

一、Sentinel的介绍

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
  Sentinel是阿里中间件团队开源的,面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。

1.1 限流的作用

  保护系统避免被瞬时流量冲垮
  预防恶意请求
  针对请求进行限制
    服务器
    应用(接口的处理能力(QPS/TPS))。RT ->Jmeter(压测)
    资源限制(cpu(线程池)、内存()、网络资源)
  如何控制流量
    限流的指标(可以容纳的流量、已经容纳的流量、可以接受的流量)阈值
    限流的过程(通过算法来实现)
    限流的结果(处理策略)

1.2 限流的算法

计数器(Zk: RequestThrottle),线程池大小,连接数大小。

滑动窗口(TCP协议会自动改变滑动窗口的大小,
在这里插入图片描述

漏桶(控制传输速率)
  水的流出速度是固定的
  桶的大小也是固定的
在这里插入图片描述

令牌桶算法
在这里插入图片描述

1.3 限流的实现

Guava

<dependency>
     <groupId>com.google.guava</groupId>
     <artifactId>guava</artifactId>
     <version>22.0</version>
</dependency>

public class RateLimiterDemo {
    //令牌桶算法
    RateLimiter rateLimiter=RateLimiter.create(10); //TPS=10
    public void doRequest(){
        if(rateLimiter.tryAcquire()){ //获取令牌
            System.out.println("success");
        }else{
            System.out.println("failed");
        }
    }
    public static void main(String[] args) {
    }
}

Semphore
分布式限流

1.4 Sentinel(看官方文档)

1、Sentinel流程图
在这里插入图片描述

2、Sentinel的定义
Sentinel是阿里中间件团队开源的,面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制,熔断降级,系统负载保护等多个维度来帮助用户保护服务的稳定性
3、Sentinel的技术图
在这里插入图片描述

二、Sentinel的使用

2.1 建立项目并且选择Spring Cloud Alibaba Sentinel

在这里插入图片描述

2.2 导入依赖

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

2.3 创建sentinelDemo并且进行编写

public class SentinelDemo {

    public static void main(String[] args) {

        while (true){
            initFlowRule();             //初始化限流规则
            //ResourceName表示资源,控制访问流量的点
            try (Entry entry= SphU.entry("helloWorld")){
                System.out.println("hello world");
            } catch (BlockException e) {
                System.out.println("被拒绝");
            }
        }
    }
    //限流规则
    private static void initFlowRule(){
        List<FlowRule> rules=new ArrayList<>();
        FlowRule flowRule=new FlowRule();
        //如果这里写helloWorld会显示被拒绝(限流)但是不写入helloworld则不会
        flowRule.setResource("helloWorld123");          //针对那个资源设置规则
        flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS); //QPS或者并发数
        rules.add(flowRule);
        FlowRuleManager.loadRules(rules);

    }
}

2.4 查询结果

flowRule.setResource(“helloWorld123”); 因为不是针对helloWorld,所以请求成功

在这里插入图片描述
flowRule.setResource(“helloWorld”); 因为针对了helloWorld,导致限流,所以请求被拒绝
在这里插入图片描述

2.5 服务熔断

  通过并发线程数进行限制
  针对响应时间

在这里插入图片描述

创建TestService服务

@Service
public class TestService {

    @SentinelResource(value = "doTest",blockHandler ="blockHandler",fallback = "fallback") //声明限流的资源
    public String doTest(String name){
        return "hello , "+name;
    }
    public String blockHandler(String name, BlockException e){ //降级,限流触发的
       return "被限流了";
    }
    public String fallback(String name){ //熔断触发的
        return "被降级了";
    }
}

创建SentinelController

@RestController
public class SentinelController {

    @Autowired
    TestService testService;

    @GetMapping("/hello/{name}")
    public String sayHello(@PathVariable("name") String name){
        return testService.doTest(name);
    }
}

在Springboot启动类中添加initFlowRule

@SpringBootApplication
public class SpringbootSentinelApplication {

    public static void main(String[] args) {
        initFlowRule();
        SpringApplication.run(SpringbootSentinelApplication.class, args);
    }

    private static void initFlowRule() {
        List<FlowRule> rules = new ArrayList<>();
        FlowRule flowRule = new FlowRule();
        flowRule.setResource("doTest"); //针对那个资源设置规则
        flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);//QPS或者并发数
        flowRule.setCount(5); //QPS=5
        rules.add(flowRule);
        FlowRuleManager.loadRules(rules);
    }
}

进入页面显示,访问成功
在这里插入图片描述

快速刷新页面,会发现被限流,会进入限流处理的事务(如果不写限流处理事务则会报500错误)
在这里插入图片描述
详解:如果有blockHandler 触发blockHandler ,有fallback 触发fallback 两者都有触发blockHandler

三、Sentinel中的流量控制

正常,则通过
被限制,抛出FlowException(FlowException extends BlockException)
同一个资源创建不同的规则,List
一个规则有什么组成
  1、resource资源
  2、count阈值
  3、grade
  4、limitApp 针对的调用来源
  5、strategy,调用关系限流
  6、controllBehavior(直接拒绝,冷启动,匀速排队)

流量控制的两种方法

  并发线程数量
  QPS


  资源
  规则
  Entry->请求

限流规则的核心因素


  resource
  count
  grade
  limitApp

并发线程数


  Hystrix   线程池隔离
  Sentinel   并发线程数

QPS(TPS)


策略(流量控制的策略


  直接拒绝
  warmup
    Dubbo,负载均衡策略时候
  匀速排队
通过ControllerBehavior属性来控制策略

基于调用关系来做流量控制(纬度)


  Flowule
    limitApp
  根据调用方来限流
  根据调用链路入口来限流
  针对具有关系的资源来限流

四、Sentinel控制台

1、下载sentinel-dashboard-1.8.4.jar
2、通过指令启动Sentinel控制台

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

3、配置文件挂载到控制台上
导入依赖

<dependency>
   <groupId>com.alibaba.csp</groupId>
   <artifactId>sentinel-transport-simple-http</artifactId>
</dependency>
# Sentinel 控制台地址
spring.cloud.sentinel.transport.dashboard=localhost:8777

在这里插入图片描述
4、登录Sentinel
账号密码默认为sentinel
在这里插入图片描述
挂载成功显示
在这里插入图片描述
5、Jmeter进行压测
打开Jmeter新建一个Http请求
配置线程池
在这里插入图片描述

配置http请求
在这里插入图片描述

运行测试,观察控制台可以看见波动
在这里插入图片描述

五、动态限流规则

config center: zookeeper / apollo / etcd / redis / Consul / Eureka / Nacos

规则的感知(Pull,Push)

在这里插入图片描述

DataSource(接口)


pull
push

Sentinel扩展(InitFunc实现)


原来代码是放在主方法里面的

@SpringBootApplication
public class SpringBootSentinelApplication {

    public static void main(String[] args) {
        initFlowRule();
        SpringApplication.run(SpringBootSentinelApplication.class, args);
    }
    /**
     *定义限流规则,初始化规则方便使用
     */
    private static void initFlowRule(){
        List<FlowRule> rules = new ArrayList<>();
        FlowRule flowRule = new FlowRule();
        //绑定规则名称,针对那个规则设置规则
        flowRule.setResource("doTest");
        //QPS或者并发数
        flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        //QPS=5
        flowRule.setCount(5);
        //添加规则
        rules.add(flowRule);
            FlowRuleManager.loadRules(rules);
    }
}

现在创建FlowRuleInitFunc 引用InitFunc接口

public class FlowRuleInitFunc implements InitFunc {
    @Override
    /**
     *定义限流规则,初始化规则方便使用
     */
    public void init() throws Exception {
        List<FlowRule> rules = new ArrayList<>();
        FlowRule flowRule = new FlowRule();
        //绑定规则名称,针对那个规则设置规则
        flowRule.setResource("doTest");
        //QPS或者并发数
        flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        //QPS=5
        flowRule.setCount(5); 
        //添加规则
        rules.add(flowRule);
        FlowRuleManager.loadRules(rules);
    }
}

接着将对应的类名添加到位于资源目录(通常是 resource 目录)下的 META-INF/services 目录下的 com.alibaba.csp.sentinel.init.InitFunc 文件中,比如我们将上述的 com.test.init.DataSourceInitFunc 添加到文件中。当初次访问任意资源的时候,Sentinel 就可以自动去注册对应的数据源了。
在这里插入图片描述

com.gupaoedu.example.springbootsentinel.FlowRuleInitFunc

这样可以不用在启动类下面去写规则

六、使用Nacos设置限流规则

1. 导入依赖

<dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <version>1.8.0</version>
</dependency>

2.编写方法

public class FlowRuleInitFunc implements InitFunc {

    private final String nacosAddress = "127.0.0.1:8848";
    private final String groupId = "SENTINEL_GROUP";
    private final String dataId ="SpringBoot-sentinel";
    @Override
    /**
     *定义限流规则,初始化规则方便使用
     */
    public void init() throws Exception {
        List<FlowRule> rules = new ArrayList<>();
//        FlowRule flowRule = new FlowRule();
//        //绑定规则名称,针对那个规则设置规则
//        flowRule.setResource("resource_Name");
//        //QPS或者并发数
//        flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
//        //QPS=5
//        flowRule.setCount(5);
//        //添加规则
//        rules.add(flowRule);
//        FlowRuleManager.loadRules(rules);
        //从远程服务器加载规则(Nacos)
        ReadableDataSource<String,List<FlowRule>> flowRuleDs =
                new NacosDataSource<List<FlowRule>>(nacosAddress,groupId,dataId,
                        s -> JSON.parseObject(s,new TypeReference<List<FlowRule>>(){}));

        FlowRuleManager.register2Property(flowRuleDs.getProperty());
    }
}

3.在Nacos中编写规则

在这里插入图片描述
在这里插入图片描述

4. 进行测试,发现配置成功

在这里插入图片描述

5. 使用集成方式利用nacos编写规则

1.在nacos中设置规则(上述已经设置)
2.在配置文件中进行编辑
在application.properties

#使用nacos编辑规则方便Sentinel熔断降级机制的使用
spring.cloud.sentinel.datasource.dsl.nacos.serverAddr=127.0.0.1
spring.cloud.sentinel.datasource.dsl.nacos.dataId=Springboot-sentinel
spring.cloud.sentinel.datasource.dsl.nacos.groupId=SENTINEL_GROUP
spring.cloud.sentinel.datasource.dsl.nacos.dataType=json
spring.cloud.sentinel.datasource.dsl.nacos.ruleType=flow
spring.cloud.sentinel.datasource.dsl.nacos.username=nacos
spring.cloud.sentinel.datasource.dsl.nacos.password=nacos

3、流控规则显示成功
在这里插入图片描述

七、使用集群的方式限制流量规则

1.集群示意图

在这里插入图片描述

2.建立project sentinel-token-sever

3.添加依赖

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.chaoxing.sentinel</groupId>
  <artifactId>sentinel-token-sever</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>sentinel-token-sever</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.alibaba.csp</groupId>
      <artifactId>sentinel-cluster-server-default</artifactId>
      <version>1.8.0</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba.csp</groupId>
      <artifactId>sentinel-datasource-nacos</artifactId>
      <version>1.8.0</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba.csp</groupId>
      <artifactId>sentinel-transport-simple-http</artifactId>
      <version>1.8.0</version>
    </dependency>***
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
      </plugins>
    </pluginManagement>
      <plugins>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <configuration>
                  <source>8</source>
                  <target>8</target>
              </configuration>
          </plugin>
      </plugins>
  </build>
</project>

4.建立服务类ClusterService

public class ClusterServer {
    public static void main(String[] args) throws Exception {
        ClusterTokenServer tokenServer = new SentinelDefaultTokenServer();
        //手动载入namespace和ClusterServerConfigManager
        //集群限制流服务端通信相关配置
        ClusterServerConfigManager.loadGlobalTransportConfig(new ServerTransportConfig().setIdleSeconds(600).setPort(9999));
       //加载namespace集合列表
        ClusterServerConfigManager.loadServerNamespaceSet(Collections.singleton("APP-Test"));
        tokenServer.start();
        //Token-client会上报自己的project.name到token-server会根据namespace来统一
    }
}

5.建立获取配置类FlowRuleInitFunc

public class FlowRuleInitFunc implements InitFunc {

    private final String nacosAddress = "127.0.0.1:8848";
    private final String groupId = "SENTINEL_GROUP";
    private final String dataId ="-flow-rules";
    @Override
    /**
     *定义限流规则,初始化规则方便使用
     */
    public void init() throws Exception {
        ClusterFlowRuleManager.setPropertySupplier(namespace->{
            ReadableDataSource<String,List<FlowRule>> flowRuleDs =
                    new NacosDataSource<List<FlowRule>>(nacosAddress,groupId,namespace+dataId,
                            s -> JSON.parseObject(s,new TypeReference<List<FlowRule>>(){}));
            return flowRuleDs.getProperty();
        });
    }
}

6.添加从nacos获取配置的配置文件

在这里插入图片描述

7. 添加VM在这里插入图片描述

-Dcsp.sentinel.dashboard.server=127.0.0.1:8080   -Dproject.name=sentinel-token-sever

8.在nacos中配置

在这里插入图片描述

9.运行

在这里插入图片描述

10.客户端连接

public class FlowRuleInitFunc implements InitFunc {

    private final String nacosAddress = "127.0.0.1:8848";
    private final String groupId = "SENTINEL_GROUP";
    private final String dataId ="-flow-rules";
    private  final String clusterServerHost="localhost";
    private final  int clusterServerPort=9999;
    private final int requestTimeOut=20000;
    private final String appname = "App-Test";
    @Override
    /**
     *定义限流规则,初始化规则方便使用
     */
    public void init() throws Exception {
      loadClusterConfig();
      registerFlowRule();
   }
   private  void  loadClusterConfig(){
       ClusterClientAssignConfig assignConfig = new ClusterClientAssignConfig();
       assignConfig.setServerHost(clusterServerHost);//放到配置中心
       assignConfig.setServerPort(clusterServerPort);
       ClusterClientConfigManager.applyNewAssignConfig(assignConfig);
       ClusterClientConfig clientConfig = new ClusterClientConfig();
       clientConfig.setRequestTimeout(requestTimeOut);//放到配置中心
       ClusterClientConfigManager.applyNewConfig(clientConfig);
   }
   private void registerFlowRule(){
        ReadableDataSource<String,List<FlowRule>> flowRuleDs =
                new NacosDataSource<List<FlowRule>>(nacosAddress,groupId,appname+dataId,
                       s -> JSON.parseObject(s,new TypeReference<List<FlowRule>>(){}));
        FlowRuleManager.register2Property(flowRuleDs.getProperty());
   }
} 

11.设置主方法为客户端

@SpringBootApplication
public class SpringbootSentinelApplication {

    public static void main(String[] args) {
        ClusterStateManager.applyState(ClusterStateManager.CLUSTER_CLIENT);     //表示是客户端
        SpringApplication.run(SpringbootSentinelApplication.class, args);
    }
}

12.调试vm options(名字要相同)

在这里插入图片描述

-Dsever.port=8888 -Dproject.name=App-Test -Dcsp.sentinel.dashboard.server=127.0.0.1:8080 

13.确定配置文件可用

在这里插入图片描述

14.运行测试

在这里插入图片描述
在这里插入图片描述

连接成功

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值