通过Github下载对应的Jar包,下载地址
java -jar sentinel-dashboard-1.8.4.jar
-Dserver.port=8001 修改启动端口
-Dsentinel.dashboard.auth.username=sentinel 修改控制台登陆用户名
sentinel.dashboard.auth.password=sentinel 修改控制台登陆密码
剩下的配置可以参考官方的配置: 官方配置信息
在1.7.0版本之后还可以使用配置文件的形式来指定,但是我没实现成功
阈值类型分类
流控模式分类
流控效果分类
熔断策略分类
对请求的接口中的某个请求参数进行限流,当单位时间内的QPS超过阈值时进行限流
参数例外项:前面说的是对请求参数进行限流,也就是不管你的请求参数的值是什么都会触发,但是参数例外项则是设置当请求参数为某个值是则触发的QPS条件为设置的阈值
前面所说的限流规则都是单独针对服务中的某个具体的请求的,如果很多接口不可能每个都这么配置,所以出现了系统规则的限流方案
系统限流规则模式分类
使用代码的方式演示官网中所有的限流规则配置极其使用,并通过测试的方式直观呈现各限流规则的体现
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
dependencies>
server:
port: 8001
spring:
application:
name: sentinel-provider
cloud:
nacos:
discovery:
server-addr: http://192.168.72.130:8848
sentinel:
transport:
port: 8719
dashboard: http://192.168.72.130:8080
management:
endpoints:
web:
exposure:
include: "*"
@SpringBootApplication
@EnableDiscoveryClient
public class SentinelProvider8001 {
public static void main(String[] args){
SpringApplication.run(SentinelProvider8001.class,args);
}
}
sentinel控制台中有很多的限流规则,不一一实现了,这里实现一个比较特特殊的就是热点规则限流,它是根据请求参数中的某个具体的参数进行限流的,例如在请求中出现了A参数那么就执行我们配置的限流规则,同时也提供了特殊处理,比如如果A等于5的话就不执行设置的限流规则,控制台相关配置如下
测试接口编写
@RestController
public class TestController {
@GetMapping("/hotkey")
//p1就是我们在控制太配置的需要限流的热点参数
public String hotKey(@RequestParam(value = "p1", required = false) String p1,
@RequestParam(value = "p2", required = false) String p2) {
return "正常使用热点建规则";
}
}
分别测试接口:http://localhost:8001?p1=1&p2=10 因为设置的QPS是1所以点的快点就可以看到流控效果,在测试设置特殊热点是否不执行限流规则 http://localhost:8001?p1=5&p2=10
资源名称进行限流:控制要跟据代码中使用SentinelResource注解时使用的资源名称进行限流
地址限流:控制台限流规则配置跟据请求地址进行限流
需要在Sentinel控制台中新增对于testResource资源的限流规则下面的方案同理的也需要在Sentinel中新增对该资源的限流规则
@RestController
public class TestController{
@GetMapping("/test")
@SentinelResource(value="testResource",blockHandler="testBlockHandler")
public String test(){
return "test1";
}
//和原方法所需的参数以及返回值一致,可以额外加一个参数类型为BlockException
public String testBlockHandler(){
return "使用单个方法的限流处理";
}
}
@RestController
public class TestController{
@GetMapping("/test")
@SentinelResource(
value="testResource",
blockHandlerClass = CustomBlockHandler.class,
blockHandler = "blockHandler")
public String test(){
return "test1";
}
}
@Component
public class CustomBlockHandler{
public static String blockHandler(){
return "使用外部类的限流处理方案";
}
}
在使用外部类中的方法作为限流方案时对应的限流处理方法需要声明为静态方法
在上面的配置中限流都是针对于某个具体的接口使用@SentinelResource注解实现的,但是在使用nacos进行持久化限流规则选用系统限流配置时发现单个方法这样的配置不能够触发自定义的限流处理方案,并且如果需要进行限流的接口比较多时不可能每个都去这么使用@SentinelResource注解进行限流,回归本质问题,在没有设置自定义限流处理逻辑时也会触发默认的处理方法,只不过是Sentinel自己抛出的一个异常,DefaultBlockExceptionHandler这个类中就是Sentinel自带的限流处理逻辑,仿照这个类就可以实现自定义的全局限流方案
@Configuration
public class SentinelConfig implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
httpServletResponse.setContentType("text/json;charset=utf-8");
httpServletResponse.getWriter().write("使用配置类配置的自定义限流处理逻辑");
}
}
注意:如果同时配置了全局限流处理逻辑和单个方法的限流方法,那么方法就不会在使用全局的了,而是使用自己单独配置的限流处理逻辑
@RestControlelr
public class TestController{
@GetMapping("/test")
@SentinelResource(value="testFallback",fallbackHandler="testFallbackHandler")
public String test(){
//故意抛出错误进行降级处理
int i=10/0;
return "test1"
}
//方法的参数列表和返回值和需要降级的方法一致,可以额外多一个类型类型为Throwable的参数
public String testFallbackHandler(){
return "当个方法的降级处理策略";
}
}
fallback和defaultFallback的区别:fallback指定的降级处理方法的参数列表和返回值需要和原方法一致,defaultFallback指定的方法参数列表必须为空,并且方法的返回值必须和原方法一致,如果同时设置了fallback属性和defaultFallback属性则触发降级时会选用fallback属性指定的方法
@RestControlelr
public class TestController{
@GetMapping("/test")
@SentinelResource(value="testFallback",fallbackClass=CustomFallback.class,fallbackHandler="fallbackHandler")
public String test(){
//故意抛出错误进行降级处理
int i=10/0;
return "test1"
}
}
@Component
public class CustomFallback{
//该方法必须声明为静态方法
public static String fallbackHandler{
return "使用外部自定义降级处理方法";
}
}
**限流和降级的区别:**限流是针对于在Sentinel面板中配置的限流规则的,即达到了面板中设置的规则时进行触发,降级是在程序运行过程中触发的兜底策略,例如程序运行异常之类的。两者之间是可以同时配置的,不会有冲突
限流和降级都是针对于@SentinelResource注解进行展开的具体详细的配置流程可以参照官网给出的解释:@SentinelResource官网详细解释
1.限流规则失效场景
在Sentinel控制台中配置的限流规则在应用重启后就会消失,可以结合Nacos对限流规则进行相应的限流
引入相关依赖,除了基本的seninel的依赖之外还需要引入一个额外的,这里使用nacos来进行规则持久化配置,如果不使用nacos的话就看官网使用其他方式进行实现实现,这里不做赘述
<dependency> <groupId>com.alibaba.cspgroupId> <artifactId>sentinel-datasource-nacosartifactId> dependency>
修改配置文件
spring: application: name: sentinel-provider cloud: sentinel: transport: port: 8719 dashboard: http://192.168.72.130:8080 #获取nacos上的限流规则 datasource: flow: #限流规则名称(随意) nacos: #使用nacos进行规则持久化 username: nacos #nacos访问用户名 password: nacos #nacos访问密码 server-addr: http://192.168.72.130:8848 #nacos地址 data-type: json #nacos配置文件类型 data-id: ${spring.application.name}-sentinel-flow #nacos中限流配置文件的dataID group-id: DEFAULT_GROUP #nacos中限流规则的分组\ namespace: d7de7037-c6db-4c03-a11c-1b77f166c952 rule-type: flow #限流规则,还有其他的限流规则方式分别是
然后就可以尽情使用了
[
{
// 资源名
"resource": "/test",
// 针对来源,若为 default 则不区分调用来源
"limitApp": "default",
// 限流阈值类型(1:QPS;0:并发线程数)
"grade": 1,
// 阈值
"count": 1,
// 是否是集群模式
"clusterMode": false,
// 流控效果(0:快速失败;1:Warm Up(预热模式);2:排队等待)
"controlBehavior": 0,
// 流控模式(0:直接;1:关联;2:链路)
"strategy": 0,
// 预热时间(秒,预热模式需要此参数)
"warmUpPeriodSec": 10,
// 超时时间(排队等待模式需要此参数)
"maxQueueingTimeMs": 500,
// 关联资源、入口资源(关联、链路模式)
"refResource": "rrr"
}
]
[
{
// 资源名
"resource": "/test1",
"limitApp": "default",
// 熔断策略(0:慢调用比例,1:异常比率,2:异常计数)
"grade": 0,
// 最大RT、比例阈值、异常数
"count": 200,
// 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)
"slowRatioThreshold": 0.2,
// 最小请求数
"minRequestAmount": 5,
// 当单位统计时长(类中默认1000)
"statIntervalMs": 1000,
// 熔断时长
"timeWindow": 10
}
]
[
{
// 资源名
"resource": "/test1",
// 限流模式(QPS 模式,不可更改)
"grade": 1,
// 参数索引
"paramIdx": 0,
// 单机阈值
"count": 13,
// 统计窗口时长
"durationInSec": 6,
// 是否集群 默认false
"clusterMode": 默认false,
//
"burstCount": 0,
// 集群模式配置
"clusterConfig": {
//
"fallbackToLocalWhenFail": true,
//
"flowId": 2,
//
"sampleCount": 10,
//
"thresholdType": 0,
//
"windowIntervalMs": 1000
},
// 流控效果(支持快速失败和匀速排队模式)
"controlBehavior": 0,
//
"limitApp": "default",
//
"maxQueueingTimeMs": 0,
// 高级选项
"paramFlowItemList": [
{
// 参数类型
"classType": "int",
// 限流阈值
"count": 222,
// 参数值
"object": "2"
}
]
}
]
[
{
// RT
"avgRt": 1,
// CPU 使用率
"highestCpuUsage": -1,
// LOAD
"highestSystemLoad": -1,
// 线程数
"maxThread": -1,
// 入口 QPS
"qps": -1
}
]
[
{
"resource": "/persistence/test1",
"limitApp": "default",
"grade": 1,
"count": 1,
"clusterMode": false,
"controlBehavior": 0,
"strategy": 0
},
{
// 资源名
"resource": "/persistence/test2",
// 限流模式(QPS 模式,不可更改)
"grade": 1,
// 参数索引
"paramIdx": 1,
// 单机阈值
"count": 1,
// 统计窗口时长
"durationInSec": 1,
// 是否集群 默认false
"clusterMode": false,
"burstCount": 0,
"controlBehavior": 0,
"limitApp": "default",
"maxQueueingTimeMs": 0,
"paramFlowItemList": [
{
// 参数类型
"classType": "int",
// 限流阈值
"count": 10,
// 参数值
"object": "2"
}
]
}
]
前面配置的限流规则每当修改时就需要重启一下应用,官方也提供了动态刷新限流规则的配置。
新建配置类,实现ApplicationRunner接口主要就是想要在应用启动的时候就执行对应的程序,其余的方式不做赘述
这里不需要在客户端配置文件中写上获取限流规则的配置了,直接在这里获取就行了,配置文件中写好像是不能够支持动态刷新的
@Configuration public class FlowRuleConfig implements ApplicationRunner { //如果配合了使用从nacos中获取配曲的配置文件可以通过@NacosValue进行注入属性 //或则可以通过@configurationProperties注解从本地配置文件中进行获取 private String serverAddr="http://192.168.72.130:8848"; private String username="nacos"; private String password="nacos"; private String namespance="d7de7037-c6db-4c03-a11c-1b77f166c952"; private String groupId="DEFAULT_GROUP"; private String dataId="sentinel-provider-sentinel-flow"; @Override public void run(ApplicationArguments args) throws Exception { //配置太多可以结合Properties类进行配置 Properties properties=new Properties(); properties.setProperty(PropertyKeyConst.SERVER_ADDR,serverAddr); properties.setProperty(PropertyKeyConst.USERNAME,username); properties.setProperty(PropertyKeyConst.PASSWORD,password); properties.setProperty(PropertyKeyConst.NAMESPACE,namespance); //官方写的核心代码就是这一段 ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(properties, groupId, dataId, source -> JSON.parseObject(source, new TypeReference<>() { })); FlowRuleManager.register2Property(flowRuleDataSource.getProperty()); } }
上面的代码只是针对于使用流控规则的,如果一个持久化规则配置文件中有很多的不同的限流规则,那么就需要使用不同的规则管理器和规则类进行配置了,上面代码中的规则类和规则管理器分别就是FlowRule和FlowRuleManager,其他的规则类和管理器类都在com.alibaba.csp.sentinel.slots.block这个包下可以自行查看之后针对不同的限流规则使用不同的管理器进行注册。
配置文件中存在流控股则和系统规则时,配置类就是下面这种类型了
配置文件详情如下
[ //流控规则 { "resource": "/persistence/test1", "limitApp": "default", "grade": 1, "count": 1, "clusterMode": false, "controlBehavior": 0, "strategy": 0 }, //系统规则 { "qps":1 } ]
public void run(ApplicationArguments args) throws Exception { Properties properties=new Properties(); properties.setProperty(PropertyKeyConst.SERVER_ADDR,serverAddr); properties.setProperty(PropertyKeyConst.USERNAME,username); properties.setProperty(PropertyKeyConst.PASSWORD,password); properties.setProperty(PropertyKeyConst.NAMESPACE,namespance); //流控规则数据源配置 ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(properties, groupId, dataId, source -> JSON.parseObject(source, new TypeReference<>() { })); //系统规则数据源配置 ReadableDataSource<String, List<SystemRule>> systemRuleDataSource = new NacosDataSource<>(properties, groupId, dataId, source -> JSON.parseObject(source, new TypeReference<>() { })); //分别注册流控规则和系统规则,如果还有其他的自行衍生 FlowRuleManager.register2Property(flowRuleDataSource.getProperty()); SystemRuleManager.register2Property(systemRuleDataSource.getProperty()); }
剩下的就跟限流规则持久化的配置一样了,在nacos中配置对应的限流规则即可
sentinel版本要在1.6.0或以上,同时结合Nacos进行限流规则的持久化。这里只做网关的项目搭建,其他的服务就仅仅只是写了个接口并注册到nacos中而已没什么特殊操作
自定义API分组哪个没实现,实现了之后在sentinel控制台中只看到了一个api分组的名字没有相应的匹配规则,debug看代码也是只获取到了名字而已不知道什么原因,但是配置就是这样,就不实现了。使用RouteID配置
1.引入依赖
<dependencies> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-webartifactId> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-actuatorartifactId> dependency> <dependency> <groupId>com.alibaba.cloudgroupId> <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId> dependency> dependencies>
2.配置文件编写
server: port: 8003 spring: application: name: sentinel-gateway cloud: nacos: discovery: server-addr: http://192.168.72.130:8848 username: nacos password: nacos namespace: 26344dce-b8e5-4327-aa06-3ac40292cced group: DEFAULT_GROUP sentinel: transport: port: 8719 dashboard: http://192.168.72.130:8080 #自定义的限流响应值,也可以配置重定向页面这里使用配置文件的方式进行,当然也可以使用硬编码的方式,但是不推荐 scg: fallback: mode: response response-status: 200 response-body: '{"code":502,"msg":"系统繁忙,请稍后再试!"}' #redirect: "/error" #重定向到处理页面 gateway: #网关中的路由配置 routes: - id: service1 uri: lb://gateway-service1 predicates: - Path=/service1/** filters: - StripPrefix=1 - id: service2 uri: lb://gateway-service2 predicates: - Path=/service2/** filters: - StripPrefix=1 #这个配置不是官方的配置是我自定义的,只是为了能够使用自动属性注入而已 sentinel: gateway: rule: nacos: server-addr: http://192.168.72.130:8848 username: nacos password: nacos namespace: 26344dce-b8e5-4327-aa06-3ac40292cced group-id: DEFAULT_GROUP route-data-id: gateway-flow-rule api-data-id: gateway-rule-api-group
3.编写配置类
@Configuration @ConfigurationProperties(prefix = "sentinel.gateway.rule.nacos") @Data //实现ApplicationRunner注解使得程序启动就自动执行 public class SentinelGatewayLimitingConfig implements ApplicationRunner { private String serverAddr; private String username; private String password; private String namespace; private String groupId; private String routeDataId; private String apiDataId; public void loadLimitingRule(){ Properties properties=new Properties(); properties.setProperty(PropertyKeyConst.SERVER_ADDR,serverAddr); properties.setProperty(PropertyKeyConst.USERNAME,username); properties.setProperty(PropertyKeyConst.PASSWORD,password); properties.setProperty(PropertyKeyConst.NAMESPACE,namespace); //获取nacos中配置的限流规则 ReadableDataSource<String, Set<GatewayFlowRule>> flowRule=new NacosDataSource<>(properties, groupId, routeDataId, source -> JSON.parseObject(source, new TypeReference<>() { })); //获取nacos中配置的api分组定义规则 ReadableDataSource<String,Set<ApiDefinition>> apiDefinttion=new NacosDataSource<>(properties,groupId,apiDataId, source->JSON.parseObject(source,new TypeReference<>(){})); GatewayApiDefinitionManager.register2Property(apiDefinttion.getProperty()); GatewayRuleManager.register2Property(flowRule.getProperty()); } @Override public void run(ApplicationArguments args) throws Exception { loadLimitingRule(); } }
4.编写主启动类
@SpringBootApplication @EnableDiscoveryClient public class SentinelGateway8003 { public static void main(String[] args){ SpringApplication.run(SentinelGateway8003.class,args); } }
5.nacos编写持久化配置文件
配置文件的命名空间,group,以及dataId要和客户端配置文件中的一致
gateway-flow-rule文件主要是对限流规则的配置
[ { "resource": "service1", //和前面的针对单独的资源限流的配置是一样的,不过这里的资源名称是routeID "resourceMode":0, //使用RouteId进行限流 "limitApp": "default", "grade": 1, "count": 1, "clusterMode": false, "controlBehavior": 0, "strategy": 0 },{ "resource":"serviceTest2", //这个是API分组名称 "resourceMode":1, //使用自定义API分组进行限流 "limitApp": "default", "grade": 1, "count": 1, "clusterMode": false, "controlBehavior": 0, "strategy": 0 } ]
gateway-rule-api-group主要是对自定义API分组的配置
[ { "apiName": "serviceTest2", //api分组名称 "predicateItems": [ { "matchStrategy": "1", //匹配规则从0-2,分别匹配的是控制台中的精确,前缀,正则 "pattern": "/service2/**" //就是控制台中需要进行配置的字符串 } ] } ]
6.启动网关服务
在启动需要启动nacos和sentinel这里不做赘述但是网关客户端的启动需要添加额外的启动参数
-Dcsp.sentinel.app.type=1标记该应用是一个网关应用,可以在IDEA启动参数中配置
查看Sentinel控制台可以看到和之前的界面不太一样了
同时在点击流控规则时也可以看到在nacos配置的流控规则以及在Api管理中也可以看到在nacos中配置的api分组了