• Sentinel学习(2)——sentinel的使用,引入依赖和配置 & 对消费者进行流控 & 对生产者进行熔断降级


    前言

    Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。

    本篇博客介绍sentinel的使用,引入依赖和配置,结合案例阐述sentinel对消费者进行流控以及对生产者进行熔断降级。

    其他关于sentinel的文章如下:

    Sentinel学习(1)——CAP理论,微服务中的雪崩问题,和Hystix的解决方案 & Sentinel的相关概念 + 下载运行

    在这里插入图片描述

    引出


    1.sentinel的使用,引入依赖和配置;
    2.对消费者进行流控;
    3.对生产者进行熔断降级;

    一、sentinel的使用准备

    1.上下文和资源

    上下文( Context )和 context-name
    Context 代表调用链路上下文。是一个根节点,在整个调用链路的开始处,Sentinel 会创建上下文Context 对象,并且为它指定一个 name ,相当于根资源。在 Sentinel 中,不同的调用链路可能使用同一个上下文 Context 对象(共一个根节点)。在这里( 和 Spring MVC 整合 ),我们的调用链路都是在 sentinel_spring_web_context 中:

    在这里插入图片描述

    资源(Resource)和 resource-name
    在 Sentinel 中,对于每一份资源,Sentinel 会为赋予一个 name(或者你手动指定),和 Spring MVC整合时,Sentinel 使用的是 URI 来作为 Controller 方法的资源名( 在这里,Controller 方法就是资源)

    在这里插入图片描述

    2.责任的划分

    对于消费者而言,进行流量控制,别人访问我,我怕自己失败,所以我要限制别人访问我的流量;

    对于生产者而言,进行熔断降级,消费者调用生产者,怕生产者出问题,所以进行熔断降级,如果被调用方,即生产者出问题时,给出相应的应对;

    在这里插入图片描述

    3,引入依赖和配置

            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-openfeignartifactId>
                <version>2.2.6.RELEASEversion>
            dependency>
    
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    spring:
      cloud:
        # nacos的配置
        nacos:
          discovery:
            # 能够注册
            register-enabled: true
            server-addr: http://192.168.111.130:8848/
            # 命名空间
            namespace: my-tianju
            # 组名
            group: DEV
    
        # sentinel的配置
        sentinel:
          transport:
            dashboard: 192.168.111.130:7777
            port: 8719
          # 这样一启动能够立马被发现,不用请求一次后才被监控
          eager: true
          # 链路相关的配置
          # 默认是true,开启上下文整合,所有链路在根节点下,链路监控就是将请求分开统计
          web-context-unify: false
    
      application:
        name: springCloud-consumer
    
    #feign:
    #  hystrix:
    #    enable: true
    
    # 打开阿里的 sentinel
    feign:
      sentinel:
        enabled: true
    
    • 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
    • 33
    • 34
    • 35

    二、对消费者进行流量控制

    QPS(Queries Per Second) 表示每秒的查询数。也就是一台服务器每秒能够响应的查询次数。

    1.单机阈值

    QPS(Queries Per Second) 表示每秒的查询数。也就是一台服务器每秒能够响应的查询次数。

    在这里插入图片描述

    请求次数过多,被sentinel限流

    在这里插入图片描述

    2.预热设置

    在系统刚启动时,允许较少的请求,随着系统逐步稳定,提升访问允许的阈值

    在这里插入图片描述

    JMeter测试post请求,需要加一下请求头参数

    在这里插入图片描述

    Ramp-up时间:线程启动的间隔时间,如果100个线程10s内启动完成,则设置Ramp-up为100/10=10s

    在这里插入图片描述

    波形图

    在这里插入图片描述

    全流程解析:
    1.开始的时候每秒允许3次;
    2.前10s内逐步提升;
    3.在10s后达到稳定值,每秒允许10次;

    在这里插入图片描述

    3.排队等待

    排队等待:也叫流量整形,它让请求以均匀的速度通过,单机阈值为每秒通过数量,其余的在队列排队等待一段时间,(即我们设置的时间,单位是毫秒),没有超过这个时间都能被及时处理,如果超过了这个等待时间针对请求的接口没有线程来处理,则抛出异常

    在这里插入图片描述

    JMeter参数设置

    在这里插入图片描述

    波形图

    在这里插入图片描述

    限流策略流程:
    1.每秒允许10个
    2.发过来50个,通过10个剩余的40个进入队列等待:
    3.在没有请求的时候,通过队列中等待的请求,

    在这里插入图片描述

    4.关联模式

    关联:/important接口的重要程度要高于 /normal接口,如果,/important接口的访问压力很大,那么,可以『牺牲』掉 /normal` 接口,全力保证 /important 接口的正常运行

    在这里插入图片描述

    JMeter参数设置

    在这里插入图片描述

    线程数设置

    在这里插入图片描述

    add成功,get被限流

    在这里插入图片描述

    高并发情况,add接口没有出现失效

    在这里插入图片描述

    补充:自定义限流异常返回

    Sentinel 返回的默认信息是 Blocked by Sentinel (flow limiting),如果你对默认响应信息不满意,你可以自定义限流返回信息。

    Sentinel 提供了 BlockExceptionHandler 接口。不管什么原因触发了 Sentinel 阻断用户的正常请求,Sentinel 都将『进入』到用户自定义的 BlockExceptionHandler 接口的实现类中,执行 handle方法,并传入当前的请求、响应对象以及异常对象,并以 handle 方法的执行结果作为返回,回传给用户。

    package com.tianju.test;
    
    import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
    import com.alibaba.csp.sentinel.slots.block.BlockException;
    import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
    import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @Component
    public class MyBlockExceptionHandler implements BlockExceptionHandler {
        @Override
        public void handle(HttpServletRequest request, HttpServletResponse response,
                           BlockException ex) throws Exception {
            String msg = null;
            if (ex instanceof FlowException) {
                msg = "该请求限流了,请稍后重试";
            } else if (ex instanceof DegradeException) {
                msg = "被熔断了";
            } else {
                msg = "其它原因";
                // ParamFlowException "热点参数限流";
                // SystemBlockException "系统规则(负载/...不满足要求)";
                // AuthorityException "授权规则不通过";
            }
            // http 状态码
            response.setStatus(500);
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Type", "application/json;charset=utf-8");
            response.setContentType("application/json;charset=utf-8");
            new ObjectMapper().writeValue(response.getWriter(), msg);
        }
    }
    
    
    • 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
    • 33
    • 34
    • 35
    • 36
    • 37

    需要说明的是:不仅仅是因为限流和熔断这一个原因会导致 BlockExceptionhandler 的handle 方法的执行,还有其它的原因也会调用这个handler方法,因此,需要对 handle 方法的BlockException 参数对象进行 instanceof 判断

    5.链路模式

    链路限流和关联限流的思路很像,假设我们要去请求某个微服务,该微服务有2个接口(/query和/add),而这两个接口又调用了同一个service层的方法(如:doSomething()方法),那么,我们可以『站在 doSomething的方法』的角度上进行设置:如果是 /query接口在调用service层的doSomething方法,那么就进行限流,而 /add接口的调用就不限流,或设置为更宽松一些的流控

    通过配置关闭 sentinel 的 URL 收敛功能

    在这里插入图片描述

    package com.tianju.consumer.service;
    
    import com.alibaba.csp.sentinel.annotation.SentinelResource;
    import org.springframework.stereotype.Service;
    
    @Service
    public class ConsumerService {
        @SentinelResource("hello")
        public String hello(){
            return "consumerService";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    链路模式,站在service层的方法的角度上

    在这里插入图片描述

    高并发add接口,没有失效

    在这里插入图片描述

    快速点击get方法,出现失效情况

    在这里插入图片描述

    三、对生产者进行熔断降级

    熔断器3个状态:

    • Closed:关闭状态,所有请求都正常访问。

    • Open:打开状态,所有请求都会被降级。

      Hystrix会对请求情况计数,当一定时间内失败请求百分比达到阈值,则触发熔断,断路器会完全打开。默认失败比例的阈值是50%,请求次数最少不低于20次。默认是 五秒之内请求20次 如果有10次失败(50%),则请求不能正常访问。

    • Half Open:半开状态,open状态不是永久的,打开后会进入休眠时间(默认是5S)。随后断路器会自动进入半开状态。

      此时会释放部分请求通过,若这些请求都是健康的,则会完全关闭断路器,否则继续保持打开,再次进行休眠计时

    在这里插入图片描述

    1.异常数

    如下配置:一秒内发送2次请求,如果有1次失败(异常),则直接熔断,然后降级

    在这里插入图片描述

    设置参数

    在这里插入图片描述

    在这里插入图片描述

    2.异常比例

    在这里插入图片描述

    设置fallback方法

    在这里插入图片描述

    package com.tianju.config;
    
    import com.tianju.common.dto.StorageDto;
    import com.tianju.common.result.HttpResp;
    import com.tianju.config.fallback.StorageFeignFallback;
    import com.tianju.entity.Order;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    
    @FeignClient(value = "storage-server",fallback = StorageFeignFallback.class)
    public interface StorageFeign {
    
        @PostMapping("/storage/sub")
        HttpResp subStorage(@RequestBody StorageDto storageDto);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    openfeign设置fallback方法

    在这里插入图片描述

    package com.tianju.config;
    
    import com.tianju.common.dto.StorageDto;
    import com.tianju.common.result.HttpResp;
    import com.tianju.config.fallback.StorageFeignFallback;
    import com.tianju.entity.Order;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    
    @FeignClient(value = "storage-server",fallback = StorageFeignFallback.class)
    public interface StorageFeign {
        @PostMapping("/storage/sub")
        HttpResp subStorage(@RequestBody StorageDto storageDto);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    生产者出现异常情况

    在这里插入图片描述

    用postman进行测试

    在这里插入图片描述

    package com.tianju.config.fallback;
    
    import com.tianju.common.dto.StorageDto;
    import com.tianju.common.result.HttpResp;
    import com.tianju.config.StorageFeign;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    
    /**
     * 调用库存的feign异常时的返回
     */
    @Component
    @Slf4j
    public class StorageFeignFallback implements StorageFeign {
        @Override
        public HttpResp subStorage(StorageDto storageDto) {
            System.out.println("#########################进入了减库存方法的异常中....###########################");
            log.debug("进入了减库存方法的异常中....");
            return HttpResp.failed("减库存的openFeign调用失效,请稍后重试");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述

    package com.tianju.config.fallback;
    
    import com.tianju.common.dto.StorageDto;
    import com.tianju.common.result.HttpResp;
    import com.tianju.config.StorageFeign;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    
    /**
     * 调用库存的feign异常时的返回
     */
    @Component
    @Slf4j
    public class StorageFeignFallback implements StorageFeign {
        @Override
        public HttpResp subStorage(StorageDto storageDto) {
            System.out.println("#########################进入了减库存方法的异常中....###########################");
            log.debug("进入了减库存方法的异常中....");
            return HttpResp.failed("减库存的openFeign调用失效,请稍后重试");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    3.慢调用比例

    如下配置:在一秒内,发5次请求,如果每次请求的响应时间超过500毫秒,这种比例达到0.5(50%),就进行熔断,熔断时长就是10秒。如:1秒内有5次请求,其中有3次请求响应时间超过了500毫秒,那么这个比例就是60%,大于50%,此时就熔断,然后降级。

    在这里插入图片描述

    用Jmeter测试,程序中当id=1时,每次响应都是800毫秒。所以每次的请求都大于500毫秒,失败率100%,这个时候去请求id=4的资源也是无法请求的,因为熔断了,所以也是直接降级。10s后再次请求id=4的就正常了。


    总结

    1.sentinel的使用,引入依赖和配置;
    2.对消费者进行流控;
    3.对生产者进行熔断降级;

  • 相关阅读:
    最新版本 Stable Diffusion 开源 AI 绘画工具之汉化篇
    FPGA与CPU进行数据通信有哪些方法?
    在 macOS 上管理 Node版本
    golang使用高阶函数优化业务功能
    rknn转换后精度差异很大,失真算子自纠
    【无标题】
    k8s-实战——Harbor镜像仓库的部署
    垃圾回收系统小程序定制开发搭建攻略
    go-micro 安装
    Linux虚拟机安装:VMware安装配置&&CentOS安装
  • 原文地址:https://blog.csdn.net/Pireley/article/details/133420975