共计 8777 个字符,预计需要花费 22 分钟才能阅读完成。
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
比照内容 | Sentinel | Hystrix |
---|---|---|
隔离策略 | 信号量隔离 | 线程池隔离 / 信号量隔离 |
熔断降级策略 | 基于响应工夫或失败比率 | 基于失败比率 |
实时指标实现 | 滑动窗口 | 滑动窗口(基于 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;
@Configuration
public 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-gateway
,hailtaxi-drvier
,hailtaxi-order
测试:
应用 postman 测试,
申请:http://localhost:8001/driver/info/1
10 秒内申请超过 2 次会被限流
申请:localhost:8001/order
1 秒内 qps 达到 2 次会被限流
本文由传智教育博学谷 – 狂野架构师教研团队公布
转载请注明出处!