什么是sentinel
Sentinel,中文翻译为哨兵,为微服务提供流量控制和熔断降级功能Hystrix同样的功能可以有效解决微服务调用产生的雪崩效应,为微服务系统提供稳定的解决方案。随着Hytrxi进入维修期,不再提供新功能,Sentinel这是一个很好的替代方案。通常情况,Hystrix利用线程池隔离服务调用,Sentinel与用户线程隔离接口相比,Hystrxi是服务级隔离,Sentinel提供接口级隔离,Sentinel隔离等级更精细,另外Sentinel与用户线程直接限制相比,Hystrix隔离线程池,减少线程切换成本。另外Sentinel的DashBoard在线改变限流规则提供配置,更加优化。
介绍官方文件,Sentinel 具有以下特点:
- 应用场景丰富: Sentinel 接近阿里巴巴 10 2001年双十一促流量的核心场景,如秒杀(即突发流量控制在系统容量可承受的范围内)、新闻峰填谷、实时熔断下游不可用应用等。
- 完备的实时监控: Sentinel 同时提供实时监控功能。您可以在控制台中看到单台机器的秒数据,甚至连接到应用程序 500 总结台下规模集群的运行情况。
- 开源生态广泛: Sentinel 与其他开源框架/库提供开箱即用集成模块,如与 Spring Cloud、Dubbo、gRPC 集成。您只需要引入相应的依赖并进行简单的配置即可快速访问 Sentinel。
- 完善的 SPI 扩展点: Sentinel 提供简单易用、完美的服务 SPI 扩展点。您可以实现扩展点,快速定制逻辑。例如,定制规则管理、适应数据源等。
下载sentinel dashboard
Sentinel dashboard提供机器发现、单机资源实时监控、集群资源实时监控、集群资源量级控制台。您只需要简单地配置应用程序就可以使用这些功能。
下载最新的sentinel dashboard,下载地址为https://github.com/alibaba/Sentinel/releases
启动端口为8748,启动命令如下:
java -Dserver.port=8748 -Dcsp.sentinel.dashboard.server=localhost:8748 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar
改造consumer
本教程的例子是基于上一节的例子。
在consumer的pom文件加上spring cloud sentinel依赖如下:
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
配置文件application.yml添加以下配置:
server: port: 8763 spring: application: name: consumer cloud: nacos: discovery: server-addr: 127.0.0.1:8848 sentinel: transport: port: 18763 dashboard: localhost:8748 feign: sentinel: enabled: true
通过feign.sentinel.enable开启Feign和sentinel自动适配sentinel的dashboard的地址。
通过如此简单的配置,Feign和sentinel配置好了。启动三个项目。provider\consumer\gateway。
多次访问浏览器http://localhost:5000/consumer/hi-feign
访问浏览器localhost:8748,登陆sentinel登录用户为的控制台sentinel,密码为sentinel。
consumer服务的/hi-feign接口,增加流控规则:
qps一、快速访问http://localhost:5000/consumer/hi-feign,会有失败。
在Spring cloud gateway上使用sentinel
Spring cloud gateway已经适配了sentinel,在gatewayg工程的pom文件加相关依赖:
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId> </dependency>
在配置文件application.yml上加上sentinel dashboard的配置:
spring: cloud: sentinel: transport: port: 15000 dashboard: localhost:8748
创建网关分组和网关限流规则,代码如下,参考https://github.com/alibaba/Sentinel/wiki/网关限流
@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; } @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() { // Register the block exception handler for Spring Cloud Gateway. return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer); } @Bean @Order(-1) public GlobalFilter sentinelGatewayFilter() { return new SentinelGatewayFilter(); } @PostConstruct public void doInit() { initCustomizedApis(); initGatewayRules(); } private void initCustomizedApis() { Set<ApiDefinition> definitions = new HahSet<>();
ApiDefinition api1 = new ApiDefinition("consumer")
.setPredicateItems(new HashSet<ApiPredicateItem>() {
{
add(new ApiPathPredicateItem().setPattern("/consumer/**")
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
ApiDefinition api2 = new ApiDefinition("provider")
.setPredicateItems(new HashSet<ApiPredicateItem>() {
{
add(new ApiPathPredicateItem().setPattern("/provider/**")
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
definitions.add(api1);
definitions.add(api2);
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}
private void initGatewayRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
rules.add(new GatewayFlowRule("consumer")
.setCount(10)
.setIntervalSec(1)
);
rules.add(new GatewayFlowRule("consumer")
.setCount(2)
.setIntervalSec(2)
.setBurst(2)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_CLIENT_IP)
)
);
rules.add(new GatewayFlowRule("provider")
.setCount(10)
.setIntervalSec(1)
.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)
.setMaxQueueingTimeoutMs(600)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_HEADER)
.setFieldName("X-Sentinel-Flag")
)
);
rules.add(new GatewayFlowRule("provider")
.setCount(1)
.setIntervalSec(1)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
.setFieldName("pa")
)
);
rules.add(new GatewayFlowRule("provider")
.setCount(2)
.setIntervalSec(30)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
.setFieldName("type")
.setPattern("warn")
.setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_CONTAINS)
)
);
rules.add(new GatewayFlowRule("provider")
.setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME)
.setCount(5)
.setIntervalSec(1)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
.setFieldName("pn")
)
);
GatewayRuleManager.loadRules(rules);
}
}
在sentinel 控制台为gateway创建一个限流规则,如下:
流控规则为qps=1,快速访问http://localhost:5000/consumer/hi-feign,在qps>1的情况下,会报以下的错误:
Blocked by Sentinel: FlowException
可见sentinel的配置已经生效,更多sentinel教程,请关注fangzhipeng.com网站。
参考文档
https://www.fangzhipeng.com/springcloud/2019/06/02/sc-sentinel.html
https://github.com/alibaba/Sentinel/releases
https://github.com/alibaba/Sentinel/tree/master/sentinel-dashboard
https://github.com/spring-cloud-incubator/spring-cloud-alibaba/wiki/Sentinel
https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0
源码下载
https://github.com/forezp/SpringCloudLearning/tree/master/sc-2020-chapter3