自学笔记:Sentinel


Sentinel

Alibaba出品的面向分布式服务架构的轻量级流量控制组件。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

流量控制:

流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。例如有时候系统会在某一瞬间接收到大量的请求,并且超过了系统的处理能力,但这个瞬间过后请求量就从峰顶跌入到谷底。此时就可以通过Sentinel 来对这请求流量进行控制。
在这里插入图片描述

熔断降级:

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

如上图,Service D出现了某些问题,例如请求响应时间长或异常比例升高,为了避免影响到其它的资源而导致级联故障,对这个资源的调用进行限制,让请求快速失败。


流量控制

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

流量控制的两种方式:

  • 并发线程数
  • QPS

限流规则的组成:

resource:规则作用的对象
count:限流阈值
grade:限流类型(QPS或并发线程数)
limiApp:针对调用来源
strategey:调用关系限流策略
controlBehavior:限流方式(直接拒绝、匀速排队、warm up)

  • 直接拒绝:当达到阈值时,新的请求会被立即拒绝,拒绝方式为抛出FlowException。
  • 匀速排队:让请求以均匀的速度通过。对应的是漏桶算法。
  • warm up:预热/冷启动方式。当流量瞬间增加时,直接将系统拉升到高水位可能会将系统压垮。通过冷启动,让通过的流量缓慢增加,直到达到阈值。

Sentinel初体验

  1. Sentinel 多样化的限流手段
  2. 如何所见即所得的配置规则
  3. 如何有效地使用 Sentinel 的监控数据
  4. 如何通过机器上报来管理机器

步骤:

  1. 下载公网demo:https://ahasoss-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/sdk/latest/ahas-sentinel-sdk-demo.jar

  2. 注册aliyun账户,开启到阿里云控制台开通 AHAS 功能。

  3. 启动公网demo

    java -Dahas.namespace=default -Dproject.name=MyDemo  -Dahas.license=53774c5320d9438cb31e5194aa4629a3 -jar ahas-sentinel-sdk-demo.jar
    
  4. 当应用开始运行后一段时间,我们刷新一下控制台页面,就可以在 AHAS Sentinel 控制台上看到我们的应用了:
    在这里插入图片描述
    在这里插入图片描述


本地应用整合sentinel

本地应用入门

构建本地应用

  1. 创建一个springBoot的基础工程,导入sentinel需要的依赖。

    		<dependency>
    			<groupId>com.alibaba.csp</groupId>
    			<artifactId>sentinel-core</artifactId>
    			<version>1.7.2</version>
    		</dependency>
    
  2. 编写controller,定义熔断降级规则,并在测试方法使用。

    @RestController
    public class HelloController {
    
        @GetMapping("hello")
        public String hello(){
            //使用 Sentinel API,使用限流规则
            try{
                SphU.entry("HelloWorld");
                return "hello Sentinel";
            } catch (BlockException e) {
                e.printStackTrace();
                return "系统繁忙";
            }
        }
    
    
        /**
         * 指定熔断降级规则
         */
        @PostConstruct      //在紧随构造方法之后执行
        public void initFlowRule(){
            //1.创建容器,用于存放规则
            List<FlowRule> rules=new ArrayList<>();
            //2.创建规则并指定规则细节
            FlowRule rule=new FlowRule();
            rule.setResource("HelloWorld");      //设置资源
            rule.setGrade(RuleConstant.FLOW_GRADE_QPS);     //设置限流规则类型,FLOW_GRADE_QPS:QPS。QPS:表示每秒查询数
            rule.setCount(2);       //设置QPS上限
            //3.将规则存入容器
            rules.add(rule);
            //4.加载规则
            FlowRuleManager.loadRules(rules);
        }
    }
    
  3. 测试:当访问每秒超过两次时:
    在这里插入图片描述

构建本地应用控制台
Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。另外,鉴权在生产环境中也必不可少。
功能:

  • 查看机器列表以及健康情况:收集 Sentinel 客户端发送的心跳包,用于判断机器是否在线。
  • 监控 (单机和集群聚合):通过 Sentinel 客户端暴露的监控 API,定期拉取并且聚合应用监控信息,最终可以实现秒级的实时监控。
  • 规则管理和推送:统一管理推送规则。
  • 鉴权:生产环境中鉴权非常重要。这里每个开发者需要根据自己的实际情况进行定制。

步骤:

  1. 下载senyinel控制台jar包:https://github.com/alibaba/Sentinel/releases

  2. 使用如下命令启动控制台

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

    -Dserver.port=9090 控制台端口号

    -Dcsp.sentinel.dashboard.server=localhost:9090 向控制台发送心跳包的控制台地址

    -Dproject.name 指定控制台名称

  3. 通过浏览器访问:http://localhost:9090/
    默认用户名和密码都是 sentinel
    在这里插入图片描述

本地应用接入本地控制台

  1. 本地应用导入依赖

            <dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-transport-simple-http</artifactId>
                <version>1.7.2</version>
            </dependency>
    
  2. 设置本地应用启动参数,并重启

    -Dcsp.sentinel.dashboard.server=127.0.0.1:9090		设置sentinel控制台的主机地址和端口
    -Dproject.name=hello							  设置本地应用在Sentinel控制台中的名称
    
  3. 此时再访问自定义的本地应用资源,则可以再sentinel进行监控
    在这里插入图片描述


定义限流规则方式

  • 直接定义一个方法
  • 控制台页面定义

控制台定义限流规则
之前的规则由于硬编码进程序中了,如果更改规则,则会比较麻烦。因此可以通过控制台页面来定义限流规则

  1. controller层:将定义规则部分除去

    @RestController
    public class HelloController {
        @GetMapping("hello")
        public String hello(){
            //使用 Sentinel API,使用限流规则
            try(Entry entry = SphU.entry("HelloWorld")){
                return "hello Sentinel";
            } catch (BlockException e) {
                e.printStackTrace();
                return "系统繁忙";
            }
        }
    }
    
  2. 再控制台页面-流控规则-新增
    在这里插入图片描述

  3. 测试:在1秒内多测访问资源,成功生效。
    在这里插入图片描述


定义资源方式

  • 抛出异常的方式定义资源
  • 返回布尔值
  • 异步调用
  • 注解
  • 主流框架默认适配
抛出异常

本地应用入门案例

返回布尔值
    @GetMapping("if")
    public String ifHello() {
        //使用 Sentinel API,使用限流规则
        if (SphO.entry("ifHello")) {
            try {
                return "ifHello Sentinel";
            } finally {
                SphO.exit();
            }
        } else {
            return "系统繁忙";
        }
    }

注意:返回布尔值定义资源所使用的sentinel API与抛出异常方式所使用的API不同。
返回布尔值:SphO
抛出异常:SphU

注意:**SphO.entry()SphO.exit()**必须成双成对出现。

测试:定义流控规则后测试
在这里插入图片描述

异步调用
  1. 在启动类上添加**@EnableAsync**表示springboot支持异步调用。

  2. 创建AsyncService编写异步方法
    方法添加**@Async**表示该方法是一个异步方法

    @Service
    public class AsyncService {
        @Async
        public void asyncTest(){
            System.out.println("异步方法开始-----");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步方法结束=====");
        }
    }
    
  3. 编写controller层,使用senyinel的API。**SphU.asyncEntry()**作为限流入口,exit()作为限流出口。

    @RestController
    public class HelloController {
    
        @Autowired
        private AsyncService asyncService;
    
        @GetMapping("async")
        public void asyncHello() {
            //使用 Sentinel API,使用限流规则
            AsyncEntry asyncEntry = null;
            try {
                asyncEntry = SphU.asyncEntry("asyncHello");	//限流入口
                asyncService.asyncTest();
            } catch (BlockException e) {
                System.out.println("系统繁忙");
            } finally {
                if (asyncEntry != null) {		//限流出口
                    asyncEntry.exit();
                }
            }
        }
    }
    
  4. 测试:定义流控规则进行测试

    在这里插入图片描述

注解

通过@SentinelResource定义注解资源,并配置blockHandler函数来进行限流之后的处理。

  1. 由于sentinel使用Aspectj的拓展自动定义资源,处理BlockException。所以需要引入依赖

    		<!--sentinel注解定义资源依赖-->
    		<dependency>
    			<groupId>com.alibaba.csp</groupId>
    			<artifactId>sentinel-annotation-aspectj</artifactId>
    			<version>1.7.2</version>
    		</dependency>
    
  2. 定义Aspectj的配置类

    @Configuration
    public class SentinelAspectConfig {
    
        @Bean
        public SentinelResourceAspect sentinelResourceAspect(){
            return new SentinelResourceAspect();
        }
    }
    
  3. 编写controller,并编写handle方法。

    @RestController
    public class AnnoController {
    
        @GetMapping("annoTest")
        @SentinelResource(value = "annoTest",blockHandler = "exceptionHandle")
        public String annoTest(){
            return "sentinel注解测试";
        }
    
        public String exceptionHandle(BlockException e){
            e.printStackTrace();
            return "系统繁忙";
        }
    }
    
  4. 测试:定义控流规则后测试
    在这里插入图片描述


Sentinel整合Springcloud

Spring Cloud Alibaba 默认为 Sentinel 整合了 Servlet、RestTemplate、FeignClient 和 Spring WebFlux。Sentinel 在 Spring Cloud 生态中,不仅补全了 Hystrix 在 Servlet 和 RestTemplate 这一块的空白,而且还完全兼容了 Hystrix 在 FeignClient 中限流降级的用法,并且支持运行时灵活地配置和调整限流降级规则。

Sentinel整合Springcloud入门

  1. 创建一个springboot工程,并导入依赖spring-cloud-starter-alibaba-sentinel

    		<dependency>
    			<groupId>com.alibaba.cloud</groupId>
    			<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    			<version>2.1.0.RELEASE</version>
    		</dependency>
    
  2. 项目中创建controller,定义资源以及blockhandler函数。

    @RestController
    public class TestController {
    
        @GetMapping("test")
        @SentinelResource(value = "sentinelTest",blockHandler = "blockExceptionHandler")
        public String test(){
            return "sentinel整合springCloud";
        }
    
        public String blockExceptionHandler(BlockException e){
            e.printStackTrace();
            return "系统繁忙,请稍后";
        }
    }
    
  3. 在配置文件中定义sentinel控制台的地址和本地应用的名称。

    spring.application.name=springCloudSentinel
    spring.cloud.sentinel.transport.dashboard=localhost:9090        
    
  4. 启动,在控制台页面添加流控规则测试。
    成功
    在这里插入图片描述


sentinel整合feign

该操作只需要在上个案例(Sentinel整合Springcloud)的基础上做两步即可

  1. 配置文件打开sentinel对feign的支持

    feign.sentinel.enabled=true
    
  2. 加入spring-cloud-starter-openfeign依赖,使sentinel starter自动化配置类生效。

案例:创建两个微服务,sentinel_feign_consumer微服务通过feign访问sentinel_feign_provider微服务。

步骤:

  1. 创建一个父工程,并导入spring-boot、spring-cloud、spring-cloud-alibaba的依赖。

    <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    
    	<groupId>com.itheima</groupId>
    	<artifactId>sentinelparent</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<modules>
    		<module>sentinel_feign_provider</module>
    		<module>sentinel_feign_consumer</module>
    	</modules>
    	<name>sentinelparent</name>
    	<packaging>pom</packaging>
    	<description>Demo project for Spring Boot</description>
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    		<java.version>1.8</java.version>
    	</properties>
    
    	<dependencyManagement>
    		<dependencies>
    			<!--spring-cloud-alibaba的依赖-->
    			<dependency>
    				<groupId>com.alibaba.cloud</groupId>
    				<artifactId>spring-cloud-alibaba-dependencies</artifactId>
    				<version>2.1.0.RELEASE</version>
    				<type>pom</type>
    				<scope>import</scope>
    			</dependency>
    			<!--spring-cloud的依赖-->
    			<dependency>
    				<groupId>org.springframework.cloud</groupId>
    				<artifactId>spring-cloud-dependencies</artifactId>
    				<version>Greenwich.RELEASE</version>
    				<type>pom</type>
    				<scope>import</scope>
    			</dependency>
    			<!--spring-boot的依赖-->
    			<dependency>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-dependencies</artifactId>
    				<version>2.1.3.RELEASE</version>
    				<type>pom</type>
    				<scope>import</scope>
    			</dependency>
    		</dependencies>
    	</dependencyManagement>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    		</plugins>
    	</build>
    
    </project>
    
  2. 创建子工程sentinel_feign_provider作为服务的生产者。

    1. 导入依赖

      <?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">
          <parent>
              <artifactId>sentinelparent</artifactId>
              <groupId>com.itheima</groupId>
              <version>0.0.1-SNAPSHOT</version>
          </parent>
          <modelVersion>4.0.0</modelVersion>
      
          <artifactId>sentinel_feign_provider</artifactId>
      
          <dependencies>
      
              <dependency>
                  <groupId>com.alibaba.cloud</groupId>
                  <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
              </dependency>
      
              <dependency>
                  <groupId>com.alibaba.cloud</groupId>
                  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
              </dependency>
      
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
      
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-openfeign</artifactId>
              </dependency>
          </dependencies>
      
      
      </project>
      
    2. 配置文件:配置nacos的配置,以及sentinel配置,开启对fen的支持

      server:
        port: 8081   #配置端口号
      spring:
        application:
          name: sentinalfeignpro   #配置本地应用名称
        cloud:
          nacos:
            discovery:
              server-addr: 127.0.0.1:8848   #配置地址值
              namespace: 766053ac-4a74-41c8-a0ae-e981dad0b86d   #命名空间:dev
          sentinel:
            transport:
              dashboard: localhost:9090    #配置sentinel地址
      feign:
        sentinel:
          enabled: true     #开启sentinel对enable的支持
      
    3. 编写controller

      @RestController
      public class ProviderController {
          private static final Logger logger= LoggerFactory.getLogger(ProviderController.class);
      
          @GetMapping("sentinelFeignTest")
          public String sentinelFeignTest(){
              logger.info("服务生产方被调用");
              return "服务生产者被调用";
          }
      
      }
      
  3. 创建子工程sentinel_feign_consumer作为服务消费方。细节与生产方大致相同。

    1. 配置文件端口不同。

    2. 编写fegin客户端,指定要调用的服务名称以及流控降级的回调类。

      @FeignClient(value = "sentinalfeignpro",fallback = FallbackService.class)
      public interface SentinelFeignProviderClient {
      
          @GetMapping("sentinelFeignTest")
          public String sentinelFeignTest();
      
      }
      
    3. 编写流控降级的回调类。

      @Component
      public class FallbackService implements SentinelFeignProviderClient {
          public String sentinelFeignTest() {
              return "服务器繁忙,稍后再试";
          }
      }
      
    4. 编写controler层,在controller层调用服务生产者。

      @RestController
      public class ConsumerController {
      
          @Autowired
          private SentinelFeignProviderClient sentinelFeignProviderClient;
      
          @GetMapping("test")
          public String test(){
              return sentinelFeignProviderClient.sentinelFeignTest();
          }
      }
      
  4. 将消费方与生产方启动

    • nacos控制台
      服务生产方与服务消费方都被注册进nacos中了
      在这里插入图片描述

    • sentinel控制台
      两个服务也都连接到sentinel控制台中去了
      在这里插入图片描述

  5. 在sentinel控制台中设置服务方的流控规则
    在这里插入图片描述

    资源命名规则:请求方式:请求协议://服务名/请求路径及参数
    GET:http://sentinalfeignpro/sentinelFeignTest

  6. 测试:频繁的访问服务消费者,成功
    在这里插入图片描述


熔断降级

由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳定,可能会导致请求发生堆积,进而导致级联错误。为了避免影响到其它的资源而导致级联故障,对这个资源的调用进行限制,让请求快速失败。当资源被降级之后,在接下来的一段时间内,对该资源的调用都自动熔断。

属性详解

Field说明默认值
resource资源名,即限流规则作用的对象
count阈值
timeWindow降级时间,在此时间内对资源的调用都会被熔断
grade熔断策略
秒级RT:平均响应时间(DEGRADE_GRADE_RT),当一秒内有N个请求,如果平均响应时间超过阈值,就会熔断
秒级异常比例:在一秒内异常的总数超过阈值就熔断,异常比例阈值范围[0.0,1.0]。
分钟级异常数:在一分钟内异常数超过阈值,则熔断。
秒级RT
rtSlowRequestAmount在秒级RT模式下,连续多少个请求的平均RT超过阈值则熔断。(1.7.0引入)5
minRequestAmount每分钟异常出现的次数如果小于该指定数,则哪怕超过异常比例也不熔断。5

**项目演示:**在sentinel整合feign项目的基础上进行演示。

  1. 在消费方编写一个新的controller

    @RestController
    public class FusingController {
    
        @SentinelResource(value = "degrade_Rule",blockHandler = "blockExceptionHandler")
        @GetMapping("degradeTest")
        public String degradeTest(){
            return "测试熔断";
        }
    
        public String blockExceptionHandler(BlockException e){
            e.printStackTrace();
            return "系统繁忙";
        }
    
        //定义熔断规则
        @PostConstruct
        private void initDegradeRule(){
            //1.创建存放规则的容器
            List<DegradeRule> rules=new ArrayList<DegradeRule>();
            //2.创建规则并制定细节
            DegradeRule rule=new DegradeRule();
            rule.setResource("degrade_Rule");
            rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);		//定义熔断类型
            rule.setTimeWindow(10);     //设置降级时间为10秒
            //3.将规则存放入容器
            rules.add(rule);
            //4.加载规则
            DegradeRuleManager.loadRules(rules);
        }
    }
    
  2. 为该controller的方法资源添加控流规则,每秒访问不超过2个。
    在这里插入图片描述

  3. 在一秒内连续访问资源超2次,如果接下来在10秒内都无法访问资源,则说明熔断成功。
    在这里插入图片描述

熔断降级规则也可以在sentinel控制台页面进行定义
降级规则-新增降级规则

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值