Spring Cloud Sentinel(限流、熔断、降级)、SpringBoot整合Sentinel、Sentinel的使用-60

一:Sentinel简介

Sentinel就是分布式系统的流量防卫兵
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

1.1 官方文档

官方文档:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

1.2 项目地址

项目地址:https://github.com/alibaba/Sentinel

1.3 特征

Spring Cloud Sentinel(限流、熔断、降级)、SpringBoot整合Sentinel、Sentinel的使用-60_第1张图片

  1. 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  2. 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
  3. 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
  4. 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

1.4 Sentinel 分为两个部分

  1. 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
  2. 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的Tomcat
  3. Sentinel 可以简单的分为 Sentinel 核心库和 Dashboard。核心库不依赖 Dashboard,但是结合 Dashboard 可以取得最好的效果。

1.5 基本概念

  • 资源
    资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
  • 规则
    围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。

1.6 主要作用——流量控制、熔断降级、系统负载保护

  1. 什么是熔断
    A 服务调用 B 服务的某个功能,由于网络不稳定问题,或者 B 服务卡机,导致功能时间超长。如果这样子的次数太多。我们就可以直接将 B 断路了(A 不再请求 B 接口),凡是调用 B 的直接返回降级数据,不必等待 B 的超长执行。 这样 B 的故障问题,就不会级联影响到 A。
  2. 什么是降级
    整个网站处于流量高峰期,服务器压力剧增,根据当前业务情况及流量,对一些服务和页面进行有策略的降级[停止服务,所有的调用直接返回降级数据]。以此缓解服务器资源的的压力,以保证核心业务的正常运行,同时也保持了客户和大部分客户的得到正确的相应。
  • 相同点:
    1、为了保证集群大部分服务的可用性和可靠性,防止崩溃,牺牲小我
    2、用户最终都是体验到某个功能不可用

  • 不同点:
    1、熔断是被调用方故障,触发的系统主动规则
    2、降级是基于全局考虑,停止一些正常服务,释放资源

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

1.7 Hystrix 与 Sentinel比较

Spring Cloud Sentinel(限流、熔断、降级)、SpringBoot整合Sentinel、Sentinel的使用-60_第2张图片
Sentinel 和 Hystrix 的原则是一致的: 当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例升高的时候,则对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联故障。

熔断降级设计理念
在限制的手段上,Sentinel 和 Hystrix 采取了完全不一样的方法。Hystrix 通过 线程池隔离 的方式,来对依赖(在 Sentinel 的概念中对应 资源)进行了隔离。这样做的好处是资源和资源之间做到了最彻底的隔离。缺点是除了增加了线程切换的成本(过多的线程池导致线程数目过多),还需要预先给各个资源做线程池大小的分配。

Sentinel 对这个问题采取了两种手段:

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

二:SpringBoot整合Sentinel

2.1 引入依赖

<dependency>
     <groupId>com.alibaba.cloudgroupId>
     <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>

2.2 下载sentinel-dashboard的jar包

Spring Cloud Sentinel(限流、熔断、降级)、SpringBoot整合Sentinel、Sentinel的使用-60_第3张图片
使用 java -jar sentinel-dashboard-1.6.3.jar启动sentinel
Spring Cloud Sentinel(限流、熔断、降级)、SpringBoot整合Sentinel、Sentinel的使用-60_第4张图片
注:默认是8080端口,如果8080端口被占用,那么可以修改对应的端口号

 java -jar sentinel-dashboard-1.6.3.jar --server.port=8333

Spring Cloud Sentinel(限流、熔断、降级)、SpringBoot整合Sentinel、Sentinel的使用-60_第5张图片
成功启动!!!!

2.3 配置sentinel控制台地址信息

作用就是将信息收集到控制台

# 控制台地址配置
spring.cloud.sentinel.transport.dashboard=127.0.0.1:8333
# 传输端口
spring.cloud.sentinel.transport.port=8719

2.4 实时监控——endpoint支持

1)每一个微服务都引入actuator信息审计模块依赖
在springboot模块添加此依赖,可以实时统计应用的健康状况信息,请求调用信息。sentinel可以获取到这些信息进行实时监控

         <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>

2)暴露endpoint端口

#暴露所有端点
management.endpoints.web.exposure.include=*

2.5 自定义sentinel流控返回数据

1)新建配置类

@Configuration
public class GulimailSeckillSentinelConfig {

    public GulimailSeckillSentinelConfig() {

        WebCallbackManager.setUrlBlockHandler(new UrlBlockHandler() {
            @Override
            public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws IOException {
                R error = R.error(BizCodeEnume.TO_MANY_REQUEST.getCode(), BizCodeEnume.TO_MANY_REQUEST.getMsg());
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json");
                response.getWriter().write(JSON.toJSONString(error));

            }
        });

    }

}

2)进行全局配置

三:使用sentinel对feign的远程调用进行保护

3.1 调用方的熔断保护机制

3.1.1 引入依赖

引入openfeign依赖

        >
            >org.springframework.cloud>
            >spring-cloud-starter-openfeign>
        >

引入sentinel依赖

        <!--sentinel依赖-->
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-sentinel
        

3.1.2 加入配置

feign.sentinel.enabled=true

此时就可以检测到feign的远程调用

3.1.3 修改feign的远程调用接口

@feignClient注解中添加fallback回调方法

@FeignClient(value = "gulimail-seckill",fallback = SeckillFeignServiceFallBack.class)

添加回调实现类

@Component
@Slf4j
public class SeckillFeignServiceFallBack implements SeckillFeignService {
    @Override
    public R getSkuSeckillInfo(Long skuId) {
        log.info("熔断方法调用。。。getSkuSeckillInfo");
        return R.error(BizCodeEnume.TO_MANY_REQUEST.getCode(),BizCodeEnume.TO_MANY_REQUEST.getMsg());
    }
}

3.2 调用方手动指定远程服务的降级策略

Spring Cloud Sentinel(限流、熔断、降级)、SpringBoot整合Sentinel、Sentinel的使用-60_第6张图片
RT:超过1ms就会降级
时间窗口:在这10秒以内就不会调用此方法,等10秒过后继续尝试调用
远程服务被降级处理后,sentinel就不会调用远程服务了,默认触发熔断回调方法

3.3 设置远程服务的方法

优点:远程服务不停机,返回默认的熔断数据(限流后的数据)
缺点:超大流量浏览的时候,必须牺牲一些远程服务,远程服务指定降级规则后,此时不会运行自己的业务逻辑

四:自定义受保护资源

4.1 基于代码的方式

1)使用try-catch的方式定义受保护的资源

        try(Entry entry = SphU.entry("seckillSkus")) {
            //业务逻辑
        } catch (Exception e) {
            log.error("资源被限流:{}",e.getMessage());
            e.printStackTrace();
        }
  • seckillSkus:受保护的资源名称

2)在操作页面添加流控规则
Spring Cloud Sentinel(限流、熔断、降级)、SpringBoot整合Sentinel、Sentinel的使用-60_第7张图片

4.2 基于注解——@SentinelResource

1)添加注解

@SentinelResource(value = "getCurrentSeckillSkusResource",blockHandler = "blockHandler")

2)blockHandler——指定降级后方法的回调

blockHandler 对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

    /**
     * getCurrentSeckillSkus降级后的回调方法
     * @return
     */
    public List<SeckillSkuRedisTo> blockHandler(BlockException e){
        log.error("getCurrentSeckillSkusResource资源被限流:{}",e.getMessage());
        return null;
    }

3)fallback——针对异常的回调
fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:

  • 返回值类型必须与原函数返回值类型一致;
  • 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
  • fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

注:无论注解还是try-catch都需要配置被限流以后的默认返回,url请求可以设置统一返回:WebCallbackManager

五:网关层sentinel流控

https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81
Spring Cloud Sentinel(限流、熔断、降级)、SpringBoot整合Sentinel、Sentinel的使用-60_第8张图片

5.1 概念

Sentinel 1.6.0 引入了 Sentinel API Gateway Adapter Common 模块,此模块中包含网关限流的规则和自定义 API 的实体和管理逻辑:

  • GatewayFlowRule:网关限流规则,针对 API Gateway 的场景定制的限流规则,可以针对不同 route 或自定义的 API 分组进行限流,支持针对请求中的参数、Header、来源 IP 等进行定制化的限流。
  • ApiDefinition:用户自定义的 API 定义分组,可以看做是一些 URL 匹配的组合。比如我们可以定义一个 API 叫 my_api,请求 path 模式为 /foo/** 和 /baz/** 的都归到 my_api 这个 API 分组下面。限流的时候可以针对这个自定义的 API 分组维度进行限流。

其中网关限流规则 GatewayFlowRule 的字段解释如下:

  • resource:资源名称,可以是网关中的 route 名称或者用户自定义的 API 分组名称。
  • resourceMode:规则是针对 API Gateway 的 route(RESOURCE_MODE_ROUTE_ID)还是用户在 Sentinel 中定义的 API 分组(RESOURCE_MODE_CUSTOM_API_NAME),默认是 route。
  • grade:限流指标维度,同限流规则的 grade 字段。
  • count:限流阈值
  • intervalSec:统计时间窗口,单位是秒,默认是 1 秒。
  • controlBehavior:流量整形的控制效果,同限流规则的 controlBehavior 字段,目前支持快速失败和匀速排队两种模式,默认是快速失败。
  • burst:应对突发请求时额外允许的请求数目。
  • maxQueueingTimeoutMs:匀速排队模式下的最长排队时间,单位是毫秒,仅在匀速排队模式下生效。
  • paramItem:参数限流配置。若不提供,则代表不针对参数进行限流,该网关规则将会被转换成普通流控规则;否则会转换成热点规则。其中的字段:
    1. parseStrategy:从请求中提取参数的策略,目前支持提取来源 IP(PARAM_PARSE_STRATEGY_CLIENT_IP)、Host(PARAM_PARSE_STRATEGY_HOST)、任意 Header(PARAM_PARSE_STRATEGY_HEADER)和任意 URL 参数(PARAM_PARSE_STRATEGY_URL_PARAM)四种模式。
    2. fieldName:若提取策略选择 Header 模式或 URL 参数模式,则需要指定对应的 header 名称或 URL 参数名称。
    3. pattern:参数值的匹配模式,只有匹配该模式的请求属性值会纳入统计和流控;若为空则统计该请求属性的所有值。(1.6.2 版本开始支持)
    4. matchStrategy:参数值的匹配策略,目前支持精确匹配(PARAM_MATCH_STRATEGY_EXACT)、子串匹配(PARAM_MATCH_STRATEGY_CONTAINS)和正则匹配(PARAM_MATCH_STRATEGY_REGEX)。(1.6.2 版本开始支持)

用户可以通过 GatewayRuleManager.loadRules(rules) 手动加载网关规则,或通过 GatewayRuleManager.register2Property(property) 注册动态规则源动态推送(推荐方式)。

5.2 在网关层整合sentinel依赖


        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-alibaba-sentinel-gatewayartifactId>
            <version>2.1.0.RELEASEversion>
        dependency>

5.3 在网关控制台进行配置

Spring Cloud Sentinel(限流、熔断、降级)、SpringBoot整合Sentinel、Sentinel的使用-60_第9张图片
Spring Cloud Sentinel(限流、熔断、降级)、SpringBoot整合Sentinel、Sentinel的使用-60_第10张图片
api名称与网关配置文件的id保持一致

5.4 指定回调的类型

#回调的类型
spring.cloud.sentinel.scg.fallback.content-type=application/json
#指定回调的状态码
spring.cloud.sentinel.scg.fallback.response-status=400

六:Sentinel定制网关流控返回

添加配置类SentinelGatewayConfig

@Configuration
public class SentinelGatewayConfig {
    public SentinelGatewayConfig() {
        GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
            //网关限流了请求,就会调用此回调
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {
                R error = R.error(BizCodeEnume.TO_MANY_REQUEST.getCode(), BizCodeEnume.TO_MANY_REQUEST.getMsg());
                String errorJson = JSON.toJSONString(error);
                Mono<ServerResponse> body = ServerResponse.ok().body(Mono.just(errorJson), String.class);
                return body;
            }
        });
    }

}

你可能感兴趣的:(spring,boot,sentinel,java)