1 Sentinel主页

https://github.com/alibaba/Se...

1.1 Sentinel介绍

随着微服务的风行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的流量管制组件,次要以流量为切入点,从限流、流量整形、熔断降级、零碎负载爱护、热点防护等多个维度来帮忙开发者保障微服务的稳定性。

1)Sentinel外围组件

1:外围库(Java 客户端):不依赖任何框架/库,可能运行于 Java 7 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的反对。2:控制台(Dashboard):控制台次要负责管理推送规定、监控、集群限流调配治理、机器发现等。

2)Sentinel vs Hystrix

比照内容SentinelHystrix
隔离策略信号量隔离线程池隔离/信号量隔离
熔断降级策略基于响应工夫或失败比率基于失败比率
实时指标实现滑动窗口滑动窗口(基于 RxJava)
规定配置反对多种数据源反对多种数据源
扩展性多个扩大点插件的模式
基于注解的反对反对反对
限流基于 QPS,反对基于调用关系的限流不反对
流量整形反对慢启动、匀速器模式不反对
零碎负载爱护反对不反对
控制台开箱即用,可配置规定、查看秒级监控、机器发现等不欠缺
常见框架的适配Servlet、Spring Cloud、Dubbo、gRPC 等Servlet、Spring Cloud Netflix

3)Sentinel基本概念

  • 资源
资源是 Sentinel 的要害概念。它能够是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它利用提供的服务,甚至能够是一段代码。只有通过 Sentinel API 定义的代码,就是资源,可能被 Sentinel 爱护起来。大部分状况下,能够应用办法签名,URL,甚至服务名称作为资源名来标示资源。
  • 规定
围绕资源的实时状态设定的规定,能够包含流量管制规定、熔断降级规定以及零碎爱护规定。所有规定能够动静实时调整。

1.2 Sentinel外围性能

1.2.1 流量管制

流量管制在网络传输中是一个罕用的概念,它用于调整网络包的发送数据。然而,从零碎稳定性角度思考,在解决申请的速度上,也有十分多的考究。任意工夫到来的申请往往是随机不可控的,而零碎的解决能力是无限的。咱们须要依据零碎的解决能力对流量进行管制。Sentinel 作为一个调配器,能够依据须要把随机的申请调整成适合的形态,如下图所示:

流量管制有以下几个角度:

  • 资源的调用关系,例如资源的调用链路,资源和资源之间的关系;
  • 运行指标,例如 QPS、线程池、零碎负载等;
  • 管制的成果,例如间接限流、冷启动、排队等。

Sentinel 的设计理念是让您自由选择管制的角度,并进行灵便组合,从而达到想要的成果。

1.2.2 熔断降级

1)什么是熔断降级

除了流量管制以外,及时对调用链路中的不稳固因素进行熔断也是 Sentinel 的使命之一。因为调用关系的复杂性,如果调用链路中的某个资源呈现了不稳固,可能会导致申请产生沉积,进而导致级联谬误。

Sentinel 和 Hystrix 的准则是统一的: 当检测到调用链路中某个资源呈现不稳固的体现,例如申请响应工夫长或异样比例升高的时候,则对这个资源的调用进行限度,让申请疾速失败,防止影响到其它的资源而导致级联故障。

2)Sentinel熔断降级设计

Hystrix 通过 线程池隔离 的形式,来对依赖(在 Sentinel 的概念中对应 资源)进行了隔离。这样做的益处是资源和资源之间做到了最彻底的隔离。毛病是除了减少了线程切换的老本(过多的线程池导致线程数目过多),还须要事后给各个资源做线程池大小的调配。

Sentinel熔断降级设计:

并发线程数限度:和资源池隔离的办法不同,Sentinel 通过限度资源并发线程的数量,来缩小不稳固资源对其它资源的影响。这样岂但没有线程切换的损耗,也不须要您事后调配线程池的大小。当某个资源呈现不稳固的状况下,例如响应工夫变长,对资源的间接影响就是会造成线程数的逐渐沉积。当线程数在特定资源上沉积到肯定的数量之后,对该资源的新申请就会被回绝。沉积的线程实现工作后才开始持续接管申请。响应工夫降级:除了对并发线程数进行管制以外,Sentinel 还能够通过响应工夫来疾速降级不稳固的资源。当依赖的资源呈现响应工夫过长后,所有对该资源的拜访都会被间接回绝,直到过了指定的工夫窗口之后才从新复原。

3)零碎自适应爱护

Sentinel 同时提供零碎维度的自适应爱护能力。避免雪崩,是零碎防护中重要的一环。当零碎负载较高的时候,如果还继续让申请进入,可能会导致系统解体,无奈响应。在集群环境下,网络负载平衡会把本应这台机器承载的流量转发到其它的机器下来。如果这个时候其它的机器也处在一个边缘状态的时候,这个减少的流量就会导致这台机器也解体,最初导致整个集群不可用。

针对这个状况,Sentinel 提供了对应的爱护机制,让零碎的入口流量和零碎的负载达到一个均衡,保证系统在能力范畴之内解决最多的申请。

Sentinel集成Gateway

咱们的我的项目流量入口是SpringCloud Gateway,因而咱们重点解说Sentinel集成Gateway

3.1 Sentinel对网关反对

Sentinel 反对对 Spring Cloud Gateway、Zuul 等支流的 API Gateway 进行限流。

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

从 1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,能够提供两种资源维度的限流:

  • route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeId

    spring:    gateway:#路由配置routes:  #惟一标识符      - id: hailtaxi-driver        uri: lb://hailtaxi-driver        #路由断言        predicates:          - Path=/driver/**      #惟一标识符      - id: hailtaxi-order        uri: lb://hailtaxi-order        #路由断言        predicates:          - Path=/order/**

    主动将每个路由标识为资源,

  • 自定义 API 维度:用户能够利用 Sentinel 提供的 API 来自定义一些 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:参数限流配置。若不提供,则代表不针对参数进行限流,该网关规定将会被转换成一般流控规定;否则会转换成热点规定。其中的字段:
  • parseStrategy:从申请中提取参数的策略,目前反对提取起源 IP(PARAM_PARSE_STRATEGY_CLIENT_IP)、Host(PARAM_PARSE_STRATEGY_HOST)、任意 Header(PARAM_PARSE_STRATEGY_HEADER)和任意 URL 参数(PARAM_PARSE_STRATEGY_URL_PARAM)四种模式。

    • fieldName:若提取策略抉择 Header 模式或 URL 参数模式,则须要指定对应的 header 名称或 URL 参数名称。
  • pattern:参数值的匹配模式,只有匹配该模式的申请属性值会纳入统计和流控;若为空则统计该申请属性的所有值。(1.6.2 版本开始反对)

    • matchStrategy:参数值的匹配策略,目前反对准确匹配(PARAM_MATCH_STRATEGY_EXACT)、子串匹配(PARAM_MATCH_STRATEGY_CONTAINS)和正则匹配(PARAM_MATCH_STRATEGY_REGEX)。(1.6.2 版本开始反对)

用户能够通过 GatewayRuleManager.loadRules(rules) 手动加载网关规定,或通过 GatewayRuleManager.register2Property(property) 注册动静规定源动静推送(举荐形式)。

3.2 GateWay集成Sentinel

咱们如果想要让微服务网关集成Sentinel,须要引入依赖包,应用时只需注入对应的 SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例即可。

1、首先在hailtaxi-gateway中引入如下依赖:

<!--Sentinel--><dependency>    <groupId>com.alibaba.csp</groupId>    <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>    <version>1.8.0</version></dependency>

2、实例引入:创立配置类com.itheima.config.GatewayConfiguration:

package com.itheima.config;import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayParamFlowItem;import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;import com.alibaba.csp.sentinel.slots.block.RuleConstant;import org.springframework.beans.factory.ObjectProvider;import org.springframework.cloud.gateway.filter.GlobalFilter;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.Ordered;import org.springframework.core.annotation.Order;import org.springframework.http.codec.ServerCodecConfigurer;import org.springframework.web.reactive.result.view.ViewResolver;import javax.annotation.PostConstruct;import java.util.Collections;import java.util.HashSet;import java.util.List;import java.util.Set;@Configurationpublic class GatewayConfiguration {    private final List<ViewResolver> viewResolvers;    private final ServerCodecConfigurer serverCodecConfigurer;    public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,                                ServerCodecConfigurer serverCodecConfigurer) {        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);        this.serverCodecConfigurer = serverCodecConfigurer;    }    /**     * 限流的异样处理器     * @return     */    @Bean    @Order(Ordered.HIGHEST_PRECEDENCE)    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);    }    /***     * Sentinel路由解决外围过滤器     * @return     */    @Bean    @Order(-1)    public GlobalFilter sentinelGatewayFilter() {        return new SentinelGatewayFilter();    }    @PostConstruct    public void doInit() {        // 自定义 api 分组        initCustomizedApis();        // 初始化网关流控规定        initGatewayRules();    }    private void initCustomizedApis() {        Set<ApiDefinition> definitions = new HashSet<>();        ApiDefinition api1 = new ApiDefinition("customer_api")                .setPredicateItems(new HashSet<ApiPredicateItem>() {{                    add(new ApiPathPredicateItem().setPattern("/order/**")                            /**                             * 匹配策略:                             * URL_MATCH_STRATEGY_EXACT:url准确匹配                             * URL_MATCH_STRATEGY_PREFIX:url前缀匹配                             * URL_MATCH_STRATEGY_REGEX:url正则匹配                             */                            .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));                }});        definitions.add(api1);        GatewayApiDefinitionManager.loadApiDefinitions(definitions);    }    private void initGatewayRules() {        Set<GatewayFlowRule> rules = new HashSet<>();        rules.add(new GatewayFlowRule("hailtaxi-driver") // 资源名称,能够是网关中的 routeid或者用户自定义的 API分组名称                .setCount(2) // 限流阈值                .setIntervalSec(10) // 统计工夫窗口默认1s                .setGrade(RuleConstant.FLOW_GRADE_QPS) // 限流模式                /**                 * 限风行为:                 * CONTROL_BEHAVIOR_RATE_LIMITER 匀速排队                 * CONTROL_BEHAVIOR_DEFAULT 疾速失败(默认)                 * CONTROL_BEHAVIOR_WARM_UP:                 * CONTROL_BEHAVIOR_WARM_UP_RATE_LIMITER:                 */                .setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)                //匀速排队模式下的最长排队工夫,单位是毫秒,仅在匀速排队模式下失效                .setMaxQueueingTimeoutMs(1000)                /**                 * 热点参数限流配置                 * 若不设置,该网关规定将会被转换成一般流控规定;否则会转换成热点规定                 */                .setParamItem(new GatewayParamFlowItem()                        /**                         * 从申请中提取参数的策略:                         * PARAM_PARSE_STRATEGY_CLIENT_IP                         * PARAM_PARSE_STRATEGY_HOST                         * PARAM_PARSE_STRATEGY_HEADER                         * PARAM_PARSE_STRATEGY_URL_PARAM                         */                        .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_HEADER)                        /**                         * 若提取策略抉择 Header 模式或 URL 参数模式,                         * 则须要指定对应的 header 名称或 URL 参数名称。                         */                        .setFieldName("token")                        /**                         * 参数的匹配策略:                         * PARAM_MATCH_STRATEGY_EXACT                         * PARAM_MATCH_STRATEGY_PREFIX                         * PARAM_MATCH_STRATEGY_REGEX                         * PARAM_MATCH_STRATEGY_CONTAINS                         */                        .setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_EXACT)                        //参数值的匹配模式,只有匹配该模式的申请属性值会纳入统计和流控                        .setPattern("123456") // token=123456 10s内qps达到2次会被限流                )        );        rules.add(new GatewayFlowRule("customer_api")                /**                 * 规定是针对 API Gateway 的 route(RESOURCE_MODE_ROUTE_ID)                 * 还是用户在 Sentinel 中定义的 API 分组(RESOURCE_MODE_CUSTOM_API_NAME),默认是 route。                 */                .setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME)                .setCount(2)                .setIntervalSec(1)                .setGrade(RuleConstant.FLOW_GRADE_QPS)        );        GatewayRuleManager.loadRules(rules);    }}

此时集成就实现了。

3、启动hailtaxi-gatewayhailtaxi-drvierhailtaxi-order测试:

应用postman测试,

申请:http://localhost:8001/driver/info/1 10秒内申请超过2次会被限流

申请:localhost:8001/order 1秒内qps达到2次会被限流

本文由传智教育博学谷 - 狂野架构师教研团队公布
转载请注明出处!