学相伴Sentinel流控与降级实现
Posted 狂神说
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学相伴Sentinel流控与降级实现相关的知识,希望对你有一定的参考价值。
介绍
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来帮助您保障微服务的稳定性。
基本概念
资源
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。
只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
规则
围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
我们下载sentinelv1.8.1
版本的控制台
使用命令启动
这里server.port=9000
表示在9000端口启动
csp.sentinel.dashboard.server
指定指定控制台地址和端口project.name
指定应用名
更多的参数参见 启动参数文档。
java -Dserver.port=9000 -Dcsp.sentinel.dashboard.server=localhost:9000 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar
启动后可以访问一下localhost:9000
输入默认用户名密码sentinel
进来后可以看到当前只有我们本机一台,我们再配置一下我们的项目
新建项目,别忘了改镜像
勾选sentinel
和web
然后在配置文件配置
spring:
cloud:
sentinel:
transport:
# Sentinel 控制台地址
dashboard: localhost:9000
# 如果有多套网络,又无法正确获取本机IP,则需要使用下面的参数设置当前机器可被外部访问的IP地址,供admin控制台使用
# client-ip:
# 取消Sentinel控制台懒加载
# 默认情况下 Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包
# 配置 sentinel.eager=true 时,取消Sentinel控制台懒加载功能
eager: true
filter:
# 配置启用拦截器
enabled: true
# 配置拦截器路径
url-patterns: /**
最后启动项目
刷新控制台发现我们这台机器
我们编写一个接口,再重新启动
访问一下这个接口
成功访问后可以看到我们的簇点链路里多了这个接口
我们这里可以对它进行配置一个流控,点击流控按钮
配置QPS
为1
点击新增后我们每秒都只能请求一次了
请求多了则会被限流
我们还可以定义我们受保护的资源
简单来说,就是我们的代码块
下面这段代码可以直接试着运行一下
package com.ruben.simplesentinel;import com.alibaba.csp.sentinel.Entry;import com.alibaba.csp.sentinel.SphU;import com.alibaba.csp.sentinel.annotation.SentinelResource;import com.alibaba.csp.sentinel.slots.block.BlockException;import com.alibaba.csp.sentinel.slots.block.RuleConstant;import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;import java.util.ArrayList;import java.util.List;/**
* sentinel测试类
*
* @author <achao1441470436@gmail.com>
* @since 2021/6/29 0029 22:35
*/public class SimpleSentinelTests { public static void main(String[] args) { // 配置规则.
initFlowRules(); while (true) { // 1.5.0 版本开始可以直接利用 try-with-resources 特性
try (Entry entry = SphU.entry("HelloWorld")) { // 被保护的逻辑
System.out.println("hello world");
} catch (BlockException ex) { // 处理被流控的逻辑
System.out.println("blocked!");
}
}
} private static void initFlowRules() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("HelloWorld");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // Set limit QPS to 20.
rule.setCount(20);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
}
效果如下
我们除了使用FlowRuleManager.loadRules
去配置资源流控规则以外,还可以直接在sentinel
控制台进行配置
以及我们可以使用@SentinelResource
注解
若我们的应用使用了
Spring AOP
,我们需要通过配置的方式将SentinelResourceAspect
注册为一个 Spring Bean:@Configurationpublic class SentinelAspectConfiguration { @Bean public SentinelResourceAspect sentinelResourceAspect() { return new SentinelResourceAspect(); } }
找个地方注入这个Bean
以后
我们在service
实现类中写上这个注解
package com.ruben.simplesentinel.service.impl;import com.alibaba.csp.sentinel.annotation.SentinelResource;import com.ruben.simplesentinel.service.IHelloWorldService;import org.springframework.stereotype.Service;/**
* helloWorld业务层实现类
*
* @author <achao1441470436@gmail.com>
* @since 2021/6/29 0029 22:44
*/@Servicepublic class HelloWorldServiceImpl implements IHelloWorldService { @SentinelResource("HelloWorld") @Override
public void helloWorld() { // 资源中的逻辑
System.out.println("hello world");
}
}
然后调用
package com.ruben.simplesentinel;import com.alibaba.csp.sentinel.annotation.SentinelResource;import com.alibaba.csp.sentinel.slots.block.RuleConstant;import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;import com.ruben.simplesentinel.service.IHelloWorldService;import org.junit.jupiter.api.Test;import org.springframework.boot.test.context.SpringBootTest;import javax.annotation.Resource;import java.util.ArrayList;import java.util.List;@SpringBootTestclass SimpleSentinelApplicationTests { @Resource
private IHelloWorldService helloWorldService; @Test
void contextLoads() {
initFlowRules(); while (true) {
helloWorldService.helloWorld();
}
} private static void initFlowRules() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("HelloWorld");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // Set limit QPS to 20.
rule.setCount(20);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
}
可以看到在执行20
次后抛出了java.lang.reflect.UndeclaredThrowableException
并且是由我们com.alibaba.csp.sentinel.slots.block.flow.FlowException
导致的
除了进行限流,我们还可以直接配置降级
当我们请求几次后,就不会再执行我们的方法抛出NPE
了,因为此时我们配置的服务降级生效
小结
通过配置sentinel
限流与降级,提升了我们程序的健壮性,使得其不至于在高并发场景下压力过大。学习一门新的技术,其实查阅官方文档极其重要,这也是我的首要学习方式之一!其次就是一定要有输出,写博客、写笔记都是很棒的输出方式,希望大家能有所收获!
看完记得点个赞和在看吧,这对我们很重要哦~
长按扫码关注平台最新动态
以上是关于学相伴Sentinel流控与降级实现的主要内容,如果未能解决你的问题,请参考以下文章
springboot sentinel使用示例(基于sentinel 1.8),流控,降级,sentinel-dashboard使用,blockHandler和fallback