Sentinel 是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。
Sentinel 具有以下特性:
所有的监控、限流、熔断等等操作,都是基于“资源”做的。
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。
只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
资源在我看来即一个应用内唯一的字符串。
围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
资源和规则是多对多的关系,一个资源可以配置多个规则,一个规则也可以在多个资源内使用。
当一个资源有多个规则时,多条规则存在与关系,即逐一进行检查,全部通过才算通过。(责任链模式)
由于我们项目中已有监控平台,所以仅仅使用sentinel做一个针对某几个接口的熔断限流的操作
如果要做到全平台监控,建议使用sentinel官方推荐的集成方案,那种方案会对所有url都创建一个资源。
项目环境:springboot
主要有三个类:
<dependency>
<groupId>com.alibaba.cspgroupId>
<artifactId>sentinel-coreartifactId>
<version>1.7.2version>
dependency>
<dependency>
<groupId>com.alibaba.cspgroupId>
<artifactId>sentinel-annotation-aspectjartifactId>
<version>1.7.2version>
dependency>
/**
* @author Eric Zhao
*/
@Configuration
public class AopConfiguration {
private static final Logger log = LogUtil.getLogger(AopConfiguration.class);
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
log.info("sentinelResourceAspect 装载成功");
return new SentinelResourceAspect();
}
}
/**
* @author xs
* create time: 2020/7/24 14:48
*/
public class ResourceNameDef {
public static final String TEST_GET= "xs.test.get";
}
/**
* @author xs
* create time: 2020/7/24 14:35
*/
@Component
public class RuleDefination {
private static final Logger log = LogUtil.getLogger(RuleDefination.class);
@PostConstruct
public void loadRules() {
initFlowRule(); // 限流策略初始化
initDegradeRule(); // 熔断策略初始化
log.info("sentinel 规则定义完毕!");
}
private void initDegradeRule() {
List<DegradeRule> rules = new ArrayList<DegradeRule>();
DegradeRule rule = new DegradeRule();
rule.setResource(ResourceNameDef.TEST_GET);
// 异常率超过0.1,就认为服务不可用,执行熔断操作
rule.setCount(0.1);
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
rule.setTimeWindow(10);
rule.setMinRequestAmount(20);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
log.info("sentinel 熔断规则定义完毕!");
}
private void initFlowRule() {
List<FlowRule> rules = new ArrayList<FlowRule>();
FlowRule rule = new FlowRule();
rule.setResource(ResourceNameDef.TEST_GET);
// qps上限为1:
rule.setCount(1);
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setLimitApp("default");
rules.add(rule);
FlowRuleManager.loadRules(rules);
log.info("sentinel 限流规则定义完毕!");
}
}
定义好资源和规则之后,就可以在项目里使用了。
@RequestMapping("/test")
@RestController
public class TestCtr {
private static final Logger log = LogUtil.getLogger(TestCtr.class);
@SentinelResource(value = ResourceNameDef.TEST_GET,
fallback = "getFallback")
@RequestMapping("/get")
public ResultInfo<Integer> get() {
return ResultInfo.buildSucc(1);
}
public ResultInfo<Integer> getFallback(Throwable t) {
log.info("请求限制了:e={}, msg={}", t.getClass().getName(), t.getMessage());
return ResultInfo.buildFail();
}
}
上面的规则定义qps=1,即每秒只能进来一个请求。所以快速请求两次/test/get结果如下:
第一次:
{
"code": 1,
"message": "success"
}
第二次
{
"code": -1,
"message": "fail"
}
此时查看日志会有
2020-07-24 16:47:57.517 [http-nio-8889-exec-4] INFO xs.test.TestCtr - 请求限制了:e=com.alibaba.csp.sentinel.slots.block.flow.FlowException, msg=null
架子初步搭建完毕,可以看到限流时异常为FlowException,可以推断出不同的策略限制,会抛出不同的异常,可以针对处理。