git地址:https://github.com/sunuanwuhou/SpringCloud2020.git
Sentinel
基本知识
git: https://github.com/alibaba/Sentinel
和Hystrix: https://www.jianshu.com/p/d85c0ed44235
Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。
下载安装
官网下载安装
初始化监控
Sentinel是懒加载的,启动程序后需要访问一次,才可以监控程序
流控规则
流控模式
- 默认
QPS:
线程数:
- 关联
当关联的资源达到阀值时,就限流自己。
A关联B,B达到设定值时,A会挂掉,B不会
- 链路
链路的控制指的就是对一条链路的访问进行控制。
A服务调 testA
B服务调 testA
流控效果
-
直接失败
-
Warm Up(预热)
Sentinel的Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。warm up冷启动主要用于启动需要额外开销的场景,例如建立数据库连接等。
- 排队等待
顾名思义~
降级
https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7
- 平均响应时间 (DEGRADE_GRADE_RT):当 1s 内持续进入 N 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置。
- 异常比例 (DEGRADE_GRADE_EXCEPTION_RATIO):当资源的每秒请求量 >= N(可配置),并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
- 异常数 (DEGRADE_GRADE_EXCEPTION_COUNT):当资源近 1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。
当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都会熔断,时间窗口期后,关闭降级。
热点
https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81
我的理解是监控某个参数的,比限流颗粒度更细了
//value 是唯一标志 一般和url相同 类似于索引
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
public String testHotKey(@RequestParam(value = "p1",required = false)String p1,
@RequestParam(value = "p2",required = false)String p2) {
return "----testHotKey";
}
public String deal_testHotKey(String p1, String p2, BlockException exception) {
return "----deal_testHotKey, o(╥﹏╥)o"; // sentinel的默认提示都是: Blocked by Sentinel (flow limiting)
}
参数例外项
当热点参数为某特殊值 不进行处理 类似于白名单
系统自适应限流(全局)
https://github.com/alibaba/Sentinel/wiki/%E7%B3%BB%E7%BB%9F%E8%87%AA%E9%80%82%E5%BA%94%E9%99%90%E6%B5%81
SentinelResource
-
blockHandler
blockHandler 对应处理 BlockException 的函数名称,可选项。
blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,
参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。 -
blockHandlerClass
blockHandler 函数默认需要和原方法在同一个类中,如果希望使用其他类的函数,
则需要指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。 -
fallback
fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。
fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。 -
fallbackClass
fallbackClass的应用和blockHandlerClass类似,fallback 函数默认需要和原方法在同一个类中。
若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。 -
defaultFallback(since 1.6.0)
如果没有配置defaultFallback方法,默认都会走到这里来。
默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑。
默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。
若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。
熔断(重点)
@RequestMapping("/consumer/fallback/{id}")
// @SentinelResource(value = "fallback")
// @SentinelResource(value = "fallback",fallback ="handlerFallback")
@SentinelResource(value = "fallback",fallback ="handlerFallback",blockHandler = "blockHandler",exceptionsToIgnore = IllegalArgumentException.class)
public CommonResult<Payment> fallback(@PathVariable Long id) {
CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/" + id, CommonResult.class,id);
if(id == 4){
throw new IllegalArgumentException("IllegalArgument ,非法参数异常...");
}else if(result.getData() == null) {
throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
}
return result;
}
public CommonResult handlerFallback(@PathVariable Long id,Throwable e) {
Payment payment = new Payment(id,"null");
return new CommonResult(444,"异常handlerFallback,exception内容: " + e.getMessage(), payment);
}
public CommonResult blockHandler(@PathVariable Long id, BlockException e) {
Payment payment = new Payment(id,"null");
return new CommonResult(444,"blockHandler-sentinel 限流,BlockException: " + e.getMessage(), payment);
}
持久化(重点)
将限流规则持久化到Nacos中保存
个人觉得这里还是比较麻烦的,每一个都需要手动配置JSON.不知道有没有自动生成的
- 引入jar包
<!-- SpringCloud ailibaba sentinel-datasource-nacos 持久化需要用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
- 配置nacos对应的信息
sentinel:
transport:
#配置Sentin dashboard地址
dashboard: localhost:8080
# 默认8719端口,假如被占用了会自动从8719端口+1进行扫描,直到找到未被占用的 端口
port: 8719
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: cloudalibaba-sentinel-service
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
- 在Nacos配置对应的GroupId
[
{
"resource": "/hello",
"limitApp": "default",
"grade": 1,
"count": 5,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
resource:资源名称
limitApp:来源引用
grade:0线程 1 QPS
count:单机阀值
strategy:0 直接 1 关联 2 链路
controlBehavior:0 快速失败 1 WarmUp 2等待
clusterMode:是否集群