• Sentinel


    熔断降级限流

    什么是熔断

    A 服务调用 B 服务的某个功能,由于网络不稳定问题,或者 B 服务卡机,导致功能时间超长。如果这样子的次数太多。我们就可以直接将 B 断路了(A 不再请求 B 接口),凡是调用 B 的直接返回降级数据,不必等待 B 的超长执行。 这样 B 的故障问题,就不会级联影响到 A。

    什么是降级

    整个网站处于流量高峰期,服务器压力剧增,根据当前业务情况及流量,对一些服务和页面进行有策略的降级[停止服务,所有的调用直接返回降级数据]。以此缓解服务器资源的的压力,以保证核心业务的正常运行,同时也保持了客户和大部分客户的得到正确的相应。

    异同

    相同点:
    	1. 为了保证集群大部分服务的可用性和可靠性,防止崩溃,牺牲小我
    	2. 用户最终都是体验到某个功能不可用
    不同点:
    	1. 熔断是被调用方故障,触发的系统主动规则
    	2. 降级是基于全局考虑,停止一些正常服务,释放资源
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    什么是限流

    对打入服务的请求流量进行控制,使服务能够承担不超过自己能力的流量压力

    Sentinel 简介

    官方文档:https://github.com/alibaba/Sentinel/wiki
    项目地址:https://github.com/alibaba/Sentinel
    随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

    Sentinel 具有以下特征:
    • 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
    • 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
    • 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
    • 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
      在这里插入图片描述
    Sentinel 分为两个部分:
    • 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
    • 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的Tomcat 等应用容器。
    Sentinel 基本概念
    • 资源
      资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。
      只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
    • 规则
      围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。

    Hystrix 与 Sentinel

    在这里插入图片描述

    SpringCloud整合 (每个服务都需要)

    pom
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    控制台
    • 获取控制台
      您可以从 release 页面 下载最新版本的控制台 jar 包。

    • 启动控制台

    #如若8080端口冲突,可使用 -Dserver.port=新端口 进行设置。
    java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
    
    • 1
    • 2

    控制台默认用户名密码 sentinel

    • 配置控制台信息
      application.yml
    spring:
      cloud:
        sentinel:
          transport:
          	#传输端口 默认8719
            port: 8719
            #sentinel 服务地址
            dashboard: localhost:8080
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Endpoint 支持 统计

    pom

    <dependency>
         <groupId>org.springframework.bootgroupId>
         <artifactId>spring-boot-starter-actuatorartifactId>
     dependency>
    
    • 1
    • 2
    • 3
    • 4

    application.yml

    Spring Boot 2.x 中添加配置 management.endpoints.web.exposure.include=*。暴露的 endpoint 路径为 /actuator/sentinel

    自定义阻塞返回方法(URL限流统一返回)

    package com.jhj.gulimall.product.config;
    
    import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlBlockHandler;
    import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
    import com.alibaba.csp.sentinel.slots.block.BlockException;
    import com.alibaba.fastjson.JSON;
    import com.jhj.common.utils.R;
    import org.springframework.context.annotation.Configuration;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @Configuration
    public class SeckillSentinelConfig {
    
    
        public SeckillSentinelConfig(){
            WebCallbackManager.setUrlBlockHandler(new UrlBlockHandler() {
                @Override
                public void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws IOException {
                    R error = R.error(10000, "太多请求");
                    httpServletResponse.setCharacterEncoding("utf-8");
                    httpServletResponse.setContentType("application/json");
                    httpServletResponse.getWriter().write(JSON.toJSONString(error));
                }
            });
        }
    }
    
    
    • 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

    流控限流

    https://github.com/alibaba/Sentinel/wiki/流控限流

    当 Spring WebFlux 应用接入 Sentinel starter 后,所有的 URL 就自动成为 Sentinel 中的埋点资源,可以针对某个 URL 进行流控。不用再使用@SentinelResource(value = “sayHello”) 注解声明

    Sentinel 保护fegin远程调用 也就是熔断降级

    pom

    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-openfeignartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    给调用方 配置
    application.yml

    feign.sentinel.enabled=true
    
    • 1

    调用方抽取FeginService

    package com.jhj.gulimall.product.fegin;
    
    import com.jhj.common.to.es.SkuEsModel;
    import com.jhj.common.utils.R;
    import com.jhj.gulimall.product.fegin.fallback.SearchFeginServiceFallBack;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    
    import java.util.List;
    
    //标明那个熔断处理
    @FeignClient(value = "gulimall-search",fallback = SearchFeginServiceFallBack.class)
    public interface SearchFeginService {
        @PostMapping("/search/save/product")
        public R productStatusUp(@RequestBody List<SkuEsModel> skuEsModels);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    调用方编写熔断处理(降级返回)

    package com.jhj.gulimall.product.fegin.fallback;
    
    import com.jhj.common.to.es.SkuEsModel;
    import com.jhj.common.utils.R;
    import com.jhj.gulimall.product.fegin.SearchFeginService;
    import org.springframework.stereotype.Component;
    
    import java.util.List;
    
    @Component
    public class SearchFeginServiceFallBack implements SearchFeginService {
    
        @Override
        public R productStatusUp(List<SkuEsModel> skuEsModels) {
            return null;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    抛出异常的方式定义资源

    SphU 包含了 try-catch 风格的 API。用这种方式,当资源发生了限流之后会抛出 BlockException。这个时候可以捕捉异常,进行限流之后的逻辑处理。示例代码如下:

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

    注解方式定义资源

    Sentinel 支持通过 @SentinelResource 注解定义资源并配置 blockHandler 和 fallback 函数来进行限流之后的处理。示例:

    // 原本的业务方法.
    @SentinelResource(value="blockHandlerForGetUser" blockHandler = "blockHandlerForGetUser")
    public User getUserById(String id) {
        throw new RuntimeException("getUserById command failed");
    }
    
    // blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用
    public User blockHandlerForGetUser(String id, BlockException ex) {
        return new User("admin");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    注意 blockHandler 函数会在原方法被限流/降级/系统保护的时候调用,而 fallback 函数会针对所有类型的异常。

    @SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource 注解包含以下属性:

    • value:资源名称,必需项(不能为空)
    • entryType:entry 类型,可选项(默认为 EntryType.OUT)
    • blockHandler / blockHandlerClass: blockHandler 对应处理 BlockException 的函数名称,可选项。
      blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
    • fallback / fallbackClass:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。
      fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:
      返回值类型必须与原函数返回值类型一致;
      方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
      fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

    网关限流

    被网关控制的就不会再进入系统

    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
    dependency>
    
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-alibaba-sentinel-gatewayartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-gatewayartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    https://github.com/alibaba/Sentinel/wiki/网关限流

    配置网关限流请求,调用此回调
    package com.jhj.gulimall.gateway.config;
    
    import com.alibaba.csp.sentinel.adapter.spring.webflux.callback.BlockRequestHandler;
    import com.alibaba.fastjson.JSON;
    import com.jhj.common.utils.R;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.reactive.function.server.ServerResponse;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    @Configuration
    public class SentinelGatewayConfig {
        public SentinelGatewayConfig(){
            GatewayCallbackManager.setBlockHandler(new BlockRequestHandler(){
                //网关限流请求,调用此回调 Mono Flux
                @Override
                public Mono<ServerResponse> handleRequest(ServerWebExchange exchange,Throwable t){
                    R error = R.error(10000, "网关限流");
                    String errJson= JSON.toJSONString(error);
                    Mono<ServerResponse> body = ServerResponse.ok().body(Mono.just(errJson), String.class);
                    return body;
                }
            });
        }
    }
    
    
    • 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

    作者声明

    如有问题,欢迎指正!
    
    • 1
  • 相关阅读:
    C语言-找鞍点
    Autosar模块介绍:AutosarOS(5)
    5、JAVA入门——变量和数据类型1
    无代码开发添加数据入门教程
    强制不允许用户缩放页面
    单元测试实战(四)MyBatis-Plus 的测试
    linux使用stress命令进行压力测试cpu
    加速可编程创新,2023年英特尔FPGA中国技术日披露全矩阵FPGA产品与应用方案
    Codeforces Round 895 (Div. 3) (A~G)
    Hive学习笔记:05Hive中常用分析函数使用解析
  • 原文地址:https://blog.csdn.net/weixin_45247019/article/details/125989826