1.降级规则
降级规则就是设置当满⾜什么条件的时候,对服务进⾏降级。 Sentinel 提供了三个衡量条件:
- 慢调用比例:当资源的响应时间超过最⼤RT(以ms为单位,最⼤RT即最⼤响应时间)之后,资源进⼊准降 级状态。如果接下来1ms内持续进⼊5 个请求(最⼩请求数),他们的RT都持续超过这个阈值,那么在接下 的熔断时⻓(以s为单位)之内,就会对这个⽅法进⾏服务降级。

- 异常⽐例:当资源的每秒异常总数占通过量的⽐值数超过阈值之后,资源进⼊降级状态,即在接下来的熔断 时⻓之内,对这个⽅法的调⽤都会⾃动地返回。异常⽐率的阈值范围是[0.0,1.0]。

- 异常数:当资源近统计时⻓的异常数⽬超过阈值(异常数)之后会进⾏服务降级

1.1例子:
1.1.1慢调用比例
在controller类中新建f1方法
java
@GetMapping("/f1")
@SneakyThrows
public JsonResult f1() {
Thread.sleep(15);
return ResultTool.success("This is SentinelConsumerController`f1 method!");
}

点击一秒内大于5次出现下图所示情况

1.1.2异常比例
在controller类中新建f2方法
java
@GetMapping("/f2")
public JsonResult f2(@RequestParam("b") int b) {
int a=9/b;
return ResultTool.success("This is SentinelConsumerController`f1 method!");
}
让b=0,即为错

10秒内5次请求错两次出现下图效果

1.1.3异常数
与异常比例相同,只有下述图片内容不同

2.热点规则
热点参数流控规则是⼀种更细粒度的流控规则,它允许将规则具体到参数上。
2.1例子
2.1.1在controller类中新建g方法
java
@GetMapping("/g")
@SentinelResource("messageG")
public JsonResult g(String a,int b,char c) {
return ResultTool.success("This is SentinelConsumerController`g method!");
}
2.1.2新增热点规则

2.1.3高级选项



保存后最好再查看一下
如果是下图参数,限流100次

如果c不等于a
出现错误
3.授权规则
很多时候,我们需要根据调⽤来源来限制资源是否通过,这时候可以使⽤ Sentinel 的⿊⽩名单的功能,⿊⽩名单 根据资源的请求来源(origin)限制资源是否通过。
- 若配置⽩名单则只有请求来源位于⽩名单内时才可通过。
- 若配置⿊名单则请求来源位于⿊名单时不通过,其余的请求通过。
3.1例子
3.1.1新建parser包,在其中新建FirstRequestOriginParse类
java
package com.jiazhong.mingxing.project.cloud.sentinel.provider.parser;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
@Component
//自定义黑白名单
public class FirstRequestOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
return request.getParameter("origin");
}
}
3.2.2在controller类中新建h方法
java
@GetMapping("/h")
public JsonResult h(String origin) {
return ResultTool.success("This is SentinelConsumerController`h method!");
}

pc为白名单

pc,phone为黑名单

3.2.3header方式(使用APIPOST测试)
java
package com.jiazhong.mingxing.project.cloud.sentinel.provider.parser;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
@Component
//自定义黑白名单
public class FirstRequestOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
return request.getHeader("origin");
}
}

4.自定义异常返回
4.1整体
创建⼀个类实现BlockExceptionHandler 接⼝(整体)
java
package com.jiazhong.mingxing.project.cloud.sentinel.provider.handler;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.alibaba.fastjson.JSONArray;
import com.jiazhong.mingxing.cloud.commons.util.JsonResult;
import com.jiazhong.mingxing.cloud.commons.util.ResultTool;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.io.PrintWriter;
@Slf4j
//@Component
public class SentinelExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
log.error("SentinelExceptionHandler handle exception", e);
// BlockException 异常接⼝,包含Sentinel的五个异常
// FlowException 限流异常
// DegradeException 降级异常
// ParamFlowException 参数限流异常
// AuthorityException 授权异常
// SystemBlockException 系统负载异常
JsonResult result=null;
if (e instanceof FlowException){
result= ResultTool.fail("限流异常",401);
}else if (e instanceof DegradeException){
result=ResultTool.fail("降级异常",402);
}else if (e instanceof ParamFlowException){
result=ResultTool.fail("参数限流异常",403);
}else if (e instanceof AuthorityException){
result=ResultTool.fail("授权异常",404);
}else if (e instanceof SystemBlockException){
result=ResultTool.fail("系统负载异常",405);
}else {
result=ResultTool.fail("其他异常",406);
}
response.setContentType("application/json;charset=utf-8");
PrintWriter out=response.getWriter();
out.print(JSONArray.toJSONString(result));
}
}
依次进入Sentinel测试即可
4.2局部
新建MyBlockingAndFallbackHandler类
java
package com.jiazhong.mingxing.project.cloud.sentinel.provider.handler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.jiazhong.mingxing.cloud.commons.util.JsonResult;
import com.jiazhong.mingxing.cloud.commons.util.ResultTool;
public class MyBlockingAndFallbackHandler {
public static JsonResult aBlockingMethod(BlockException e) {
return ResultTool.fail("BlockException is"+e.getMessage(),401);
}
public static JsonResult bBlockingMethod(String name,Integer age,BlockException e) {
return ResultTool.fail("Method b blockes for name"+name+" ,BlockException is"+e.getMessage(),402);
}
public static JsonResult cFallbackMethod(int a,Throwable e) {
return ResultTool.fail("错了,"+e.getMessage(),403);
}
}
新建SentinelConsumerBlockingController接口
java
package com.jiazhong.mingxing.project.cloud.sentinel.provider.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.jiazhong.mingxing.cloud.commons.util.JsonResult;
import com.jiazhong.mingxing.cloud.commons.util.ResultTool;
import com.jiazhong.mingxing.project.cloud.sentinel.provider.handler.MyBlockingAndFallbackHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/sentinel_consumer_blocking")
public class SentinelConsumerBlockingController {
@SentinelResource(value = "aBlockingMessage", blockHandler = "aBlockingMethod",blockHandlerClass = MyBlockingAndFallbackHandler.class)
@GetMapping("/a")
public JsonResult a() {
return ResultTool.success("This is SentinelConsumerBlockingController`a method!");
}
@SentinelResource(value = "bBlockingMessage", blockHandler = "bBlockingMethod", blockHandlerClass = MyBlockingAndFallbackHandler.class)
@GetMapping("/b")
public JsonResult b(@RequestParam String name, @RequestParam Integer age) {
return ResultTool.success("This is method b with name: " + name + ", age: " + age);
}
@SentinelResource(value = "cBlockingMessage", blockHandler = "cBlockingMethod", fallback = "cFallbackMethod", fallbackClass = MyBlockingAndFallbackHandler.class)
@GetMapping("/c")
public JsonResult c(@RequestParam("a") int a) {
int result = 9 / a;
return ResultTool.success("cccc");
}
}
进入Sentinel测试即可
5.Sentinel规则持久化
通过前⾯的讲解,我们已经知道,可以通过 Dashboard 来为每个 Sentinel 客户端设置各种各样的规则,但是这 ⾥有⼀个问题,就是这些规则默认是存放在内存中,极不稳定,所以需要将其持久化。 本地⽂件数据源会定时轮询⽂件的变更,读取规则。这样我们既可以在应⽤本地直接修改⽂件来更新规则,也可以 通过 Sentinel 控制台推送规则。以本地⽂件数据源为例,推送过程如下图所示:

5.1新建持久化类
file.FilePersistence
java
package com.jiazhong.mingxing.project.cloud.sentinel.provider.file;
import com.alibaba.csp.sentinel.command.handler.ModifyParamFlowRulesCommandHandler;
import com.alibaba.csp.sentinel.datasource.*;
import com.alibaba.csp.sentinel.init.InitFunc;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import com.alibaba.csp.sentinel.transport.util.WritableDataSourceRegistry;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
import java.util.List;
@Component
public class FilePersistence implements InitFunc {
@Value("${spring.application.name}")
private String applicationName = null;
@Override
public void init() throws Exception {
System.out.println(1111111);
//指定⽂件⽣成⽬录
String applicationName = this.applicationName == null ? "cloud-sentinel-consumer" : this.applicationName;
String ruleDir = System.getProperty("user.home") + "/sentinelRules/" +
applicationName;
System.out.println("path:"+ruleDir);
String flowRulePath = ruleDir + "/flow-rule.json";
String degradeRulePath = ruleDir + "/degrade-rule.json";
String systemRulePath = ruleDir + "/system-rule.json";
String authorityRulePath = ruleDir + "/authority-rule.json";
String paramFlowRulePath = ruleDir + "/param-flow-rule.json";
this.mkdirIfNotExits(ruleDir);
this.createFileIfNotExits(flowRulePath);
this.createFileIfNotExits(degradeRulePath);
this.createFileIfNotExits(systemRulePath);
this.createFileIfNotExits(authorityRulePath);
this.createFileIfNotExits(paramFlowRulePath);
// 流控规则
ReadableDataSource<String, List<FlowRule>> flowRuleRDS = new
FileRefreshableDataSource<>(flowRulePath, flowRuleListParser);
FlowRuleManager.register2Property(flowRuleRDS.getProperty());
WritableDataSource<List<FlowRule>> flowRuleWDS = new
FileWritableDataSource<>(
flowRulePath,
this::encodeJson
);
WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS);
// 降级规则
ReadableDataSource<String, List<DegradeRule>> degradeRuleRDS = new
FileRefreshableDataSource<>(
degradeRulePath,
degradeRuleListParser
);
DegradeRuleManager.register2Property(degradeRuleRDS.getProperty());
WritableDataSource<List<DegradeRule>> degradeRuleWDS = new
FileWritableDataSource<>(
degradeRulePath,
this::encodeJson
);
WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWDS);
// 系统规则
ReadableDataSource<String, List<SystemRule>> systemRuleRDS = new
FileRefreshableDataSource<>(
systemRulePath,
systemRuleListParser);
SystemRuleManager.register2Property(systemRuleRDS.getProperty());
WritableDataSource<List<SystemRule>> systemRuleWDS = new
FileWritableDataSource<>(
systemRulePath,
this::encodeJson);
WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS);
// 授权规则
ReadableDataSource<String, List<AuthorityRule>> authorityRuleRDS = new
FileRefreshableDataSource<>(
authorityRulePath,
authorityRuleListParser
);
AuthorityRuleManager.register2Property(authorityRuleRDS.getProperty());
WritableDataSource<List<AuthorityRule>> authorityRuleWDS = new FileWritableDataSource<>(
authorityRulePath,
this::encodeJson
);
WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleWDS);
// 热点参数规则
ReadableDataSource<String, List<ParamFlowRule>> paramFlowRuleRDS = new
FileRefreshableDataSource<>(
paramFlowRulePath,
paramFlowRuleListParser
);
ParamFlowRuleManager.register2Property(paramFlowRuleRDS.getProperty());
WritableDataSource<List<ParamFlowRule>> paramFlowRuleWDS = new
FileWritableDataSource<>(paramFlowRulePath,
this::encodeJson
);
ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWDS);
}
private Converter<String, List<FlowRule>> flowRuleListParser = source ->
JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
});
private Converter<String, List<DegradeRule>> degradeRuleListParser = source
-> JSON.parseObject(
source,
new TypeReference<List<DegradeRule>>() {
});
private Converter<String, List<SystemRule>> systemRuleListParser = source ->
JSON.parseObject(
source,
new TypeReference<List<SystemRule>>() {
});
private Converter<String, List<AuthorityRule>> authorityRuleListParser =
source -> JSON.parseObject(
source,
new TypeReference<List<AuthorityRule>>() {
});
private Converter<String, List<ParamFlowRule>> paramFlowRuleListParser =
source -> JSON.parseObject(
source,
new TypeReference<List<ParamFlowRule>>() {
});
private void mkdirIfNotExits(String filePath) throws IOException {
File file = new File(filePath);
if (!file.exists()) {
file.mkdirs();
}
}
private void createFileIfNotExits(String filePath) throws IOException {
File file = new File(filePath);
if (!file.exists()) {
file.createNewFile();
}
}
private <T> String encodeJson(T t) {
return JSON.toJSONString(t);
}
}
5.2添加配置
在 resources 下创建配置⽬录 META-INF/services ,然后添加⽂件 com.alibaba.csp.sentinel.init.InitFunc 。(必须一致)
在⽂件中添加配置类的全路径

启动,在Sentinel(懒加载)中添加规则,进行测试
6.Feign 整合 Sentinel
6.1引入依赖

6.2配置文件(消费者)
在配置⽂件中开启 Feign 对 Sentinel 的⽀持

6.3修改SentinelProviderFeign
加入fallback="SentinelProviderFeignImpl.class"
java
package com.jiazhong.mingxing.project.cloud.sentinel.provider.feign;
import com.jiazhong.mingxing.cloud.commons.util.JsonResult;
import com.jiazhong.mingxing.project.cloud.sentinel.provider.feign.impl.SentinelProviderFeignImpl;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(value = "cloud-sentinel-provider", path = "sentinel_provider", fallback = SentinelProviderFeignImpl.class)
public interface SentinelProviderFeign {
@GetMapping("/a")
JsonResult a();
@GetMapping("/b")
JsonResult b();
}
6.4新建SentinelProviderFeignImpl类
java
package com.jiazhong.mingxing.project.cloud.sentinel.provider.feign.impl;
import com.jiazhong.mingxing.cloud.commons.util.JsonResult;
import com.jiazhong.mingxing.cloud.commons.util.ResultTool;
import com.jiazhong.mingxing.project.cloud.sentinel.provider.feign.SentinelProviderFeign;
import org.springframework.stereotype.Component;
@Component
public class SentinelProviderFeignImpl implements SentinelProviderFeign {
@Override
public JsonResult a() {
return ResultTool.success("你要访问sentinel_provider的a()方法,但是a方法出现了问题,我是备选方案a");
}
@Override
public JsonResult b() {
return ResultTool.success("你要访问sentinel_provider的b()方法,但是b方法出现了问题,我是备选方案b");
}
}
provider项目启动后,备选方案失效