随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
sentinel相当于hystrix的升级版,加入了web界面,能够实时在线的改变流量策略。
Sentinel 分为两个部分:
官方下载架包后运行命令:
java -Dserver.port=8858 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
访问localhost:8858 即可进入控制台界面,账户密码都为sentinel
https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
按照文档配置后,访问localhost:8080可以看到如下画面。如果没有左边的服务名,可以尝试注销账号重新登陆。
流控模式:
流控效果:
RT(平均响应时间,秒级):
异常比列(秒级)
异常数(分钟级)
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
下面的代码中参数p1,p2就是热点。deal_testHotKey为被sentinel限流后的兜底方法。
@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 e){
return "deal_testHotKey 兜底方法";
}
下面设置会统计/testHotKey携带参数0(p1)的次数,如果在统计窗口(1s)内有超过单机阈值(1条)带有参数p1的请求,则会限流。
注意:这里的blockHandler对应的兜底方法只能在sentinel限流的时候才会触发,程序异常并不会走兜底方法。
注意:参数的值应该是基本类型or String
系统保护规则是从应用级别的入口流量进行控制,从单台机器的 load、CPU 使用率、平均 RT、入口 QPS 和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(EntryType.IN),比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。
系统规则支持以下的模式:
Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5。
CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
可以另外创建一个类来进行兜底方法的配置:
public class CustomerBlockHandler {
public static CommonResult handlerException(BlockException exception){
return new CommonResult(4444,"用户自定义全局Exception: ",new Payment(2020L,"serial003"));
}
public static CommonResult handlerException2(BlockException exception){
return new CommonResult(4444,"用户自定义全局Exception: ",new Payment(2020L,"serial003-2"));
}
}
controller:通过blockHandlerClass指定类名,blockHandler指定选定的兜底方法。
@GetMapping("/byResource")
@SentinelResource(value = "byResource",blockHandlerClass = CustomerBlockHandler.class,blockHandler = "handlerException")
public CommonResult byResource(){
return new CommonResult(200,"按资源名称访问限流测试OK",new Payment(2020L,"serial001"));
}
默认情况下,当我们在Sentinel控制台中配置规则时,控制台推送规则方式是通过API将规则推送至客户端并直接更新到内存中。一旦我们重启应用,规则将消失。
引入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
修改application.yml:
spring:
cloud:
sentinel:
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-sentinel
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
在nacos中添加配置:
[
{
"resource": "/rateLimit/byUrl",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
相关参数解释:
resource:资源名称;
limitApp:来源应用;
grade:阈值类型,0表示线程数,1表示QPS;
count:单机阈值;
strategy:流控模式,0表示直接,1表示关联,2表示链路;
controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;
clusterMode:是否集群。
之后可以发现Sentinel控制台已经有了如下限流规则: