Sentinel(哨兵)是一个面向微服务的流量控制、熔断降级的组件,支持界面化的细粒度统一配置;可以对微服务进行可视化的监控和保护;同时可和nacos、dubbo、redis等结合使用。
一、后端代码中sentinel配置
1、引入pom
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、引入yml
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard地址,8080会监控8401
port: 8719 #默认为8719端口,假如被占用会自动从8719开始依次+1扫描,直到找到未被占用的端口
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: cloudalibaba-sentinel-service
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
management:
endpoints:
web:
exposure:
include: '*'
feign:
sentinel:
enabled: true # 激活Sentinel对Feign的支持
二、Sentinel 下载
1、下载地址
2、启动Nacos
3、cmd命令启动sentinel-dashboard的jar包
4、打开浏览器输入 http://localhost:8080/#/login,账号密码:sentinel
三、sentinel界面配置
sentinel属于懒加载,先访问controller中的路径,然后刷新sentinel,才会显示出来。
流量控制
(一)流量控制-直接
先访问后端代码中controller的mapping路径
@RestController
@Slf4j
public class FlowLimitController {
@GetMapping("/testA")
public String testA(){
return "----testA";
}
}
点击sentinel中左面的簇点链路,对对应的mapping(testA)进行添加流量控制
点击“流控”按钮后显示如下:
资源名:后端controller中GetMapping路径的名字。
阈值类型:QPS——每秒的请求数,当调用该api的QPS达到阈值的时候,就会进行限流。
单机阈值:1s内可以点击访问几次,如果单机阈值设置为1,表示1s内只能访问一次,如果1s内访问了多次,就会报如下错误:被Sentinel阻塞
流控模式:直接——表示是直接反应的形式。
流控效果:快速失败——表示是快速反应的形式。
(二)流量控制-关联
关联的意思是某一个服务出现了问题,让另一个服务来负责,常见的例子为:淘宝中支付的人太多,导致拥挤,这个时候可以让下单的人数降低,以维护整个系统的功能。
设置效果:
当关联资源/testB的QPS阈值超过1时,就限流/testA的访问地址
使用postman测试集合的方法:
1、
2、
3、
4、
5、点击 Run Collection之后,在访问testA,testA就会被阻塞。
(三)流量控制-预热
Warm Up:根据codeFactor(冷加载因子,默认值为3),从阈值/codeFactor开始,经过预热时长,才达到设置的QPS阈值
如上图:
单机阈值为10,冷加载因子为3,所以从10/3 = 3开始,经过5s钟之后,才达到阈值10;从点击开始,前5s会出现阻塞,5s后如果1s内的点击数量在10以下,就不会出现阻塞,是一个逐渐的过程。当秒杀系统在开启的瞬间,会有很多流量上来,给系统很大的压力,预热方式就是为了保护系统,可以慢慢的把流量放进来,慢慢的把阈值增长到设置的阈值。
(四)流量控制-排队等待
排队等待:让请求以均匀的速度通过,阈值类型必须设置为QPS,否则无效。设置含义:/testB每秒1次请求,超过的话就排队等待,等待的超时时间为2000毫秒;无论如何,它1s只执行一个请求,减缓压力。
降级服务
(一)降级-RT(平均响应时间)
1s内持续进入5个请求并且平均响应时间大于阈值,就会触发降级。
1、
2、
如上图降级策略选择的是RT——表示200ms内需要处理掉这个任务,如果1s内访问testD的线程数大于5个,并且没有在200ms内进行处理,则在1s的时间窗口内,断路器打开,微服务不可用,保险丝跳闸断电了。
(二)降级-异常比例
每秒钟持续进入5个请求,并且每秒中异常总数占通过量的比例超过阈值,资源进入降级状态,即在接下来的时间窗口(timeWindow)内,对这个方法的调用都会自动地返回。
如上图所示:
如果资源的每秒请求量>=5,并且每秒异常总数的比例超过20%,就会在接下来的3s内进入降级状态(被Sentinel阻塞)
(三)降级-异常数
当资源近1分钟的异常数目超过阈值之后会进行熔断;时间窗口一定要大于等于60s,否则结束熔断状态后仍可能再次进入熔断状态。
如上图所示:
如果1分钟内异常次数超5次之后就会进入熔断降级,进行保护:
热点
(一)概念
热点概念:热点就是我们经常访问的数据,很多时候希望统计某个热点数据中访问频次最高的数据,并对其进行访问限制。热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数热点仅仅支持QPS模式。
比如说:
商品ID为参数,统计一段时间内最常购买的商品ID并进行限制;
用户ID为参数,针对一段时间内频繁访问的用户ID进行限制。
兜底方法:当sentinel出现问题的时候,程序会走到承担问题的方法内,类似于try catch。
上面限流中出现的sentinel阻塞(Blocked by Sentinel(flow limiting))就是系统默认的一个兜底的方法;我们自己也可以设置自定义的兜底降级方法。
如上图:
1、资源名:为代码后端的请求路径(testHotKey)
2、参数索引:第一个参数的下标
3、单机阈值:1s内允许访问几次
如果第一个参数1s内访问次数超过1次,就会走后端代码中降级兜底的方法。
后端降级兜底的方法如下:
(二)热点特殊值
如果想让某一热点既限流又不限流,举例:我们希望p1参数是某一个特殊值的时候,它的限流值和平时的不一样,假如当p1为5的时候,它的阈值可以达到200,而为其他值的时候,它的阈值为1,整体来说,它既可以有普通值,又可以有特殊值。如下图设置:当第一个参数为q的时候,阈值就可以达到200。
SentinelResource配置
上面说到了自定义兜底的方法,下面进行设置:
(一)后端代码
@RestController
public class RateLimitController {
@GetMapping("/byResource")
@SentinelResource(value = "byResource",blockHandler = "handleException")
public CommonResult byResource()
{
return new CommonResult(200,"按资源名称限流测试OK",new Payment(2020L,"serial001"));
}
public CommonResult handleException(BlockException exception)
{
return new CommonResult("444",exception.getClass().getCanonicalName()+"\t 服务不可用");
}
}
(二)sentinel配置设置流控
访问 /byResource,如果1s内访问多次,就会走 “handleException”降级兜底的方法。
但是这样将业务代码和自定义处理的代码放在了一起,导致代码耦合,不直观,并且如果每一个业务方法后面都增加一个兜底的方法,那代码膨胀将会加剧;所以将兜底方法抽象出来,作为全局统一的处理方法,如下业务层的代码:
//blockHandlerClass是兜底的类,blockHandler是兜底的方法
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",
blockHandlerClass = CustomerBlockHandler.class,
blockHandler = "handlerException2")
public CommonResult customerBlockHandler()
{
return new CommonResult(200,"按客戶自定义",new Payment(2020L,"serial003"));
}
抽出来的降级兜底的类:
public class CustomerBlockHandler {
public static CommonResult handlerException2(BlockException exception)
{
return new CommonResult(444,"按客戶自定义",new Payment(2020L,"serial003"));
}
}
当进行路径访问的时候,如果出现异常则会走抽出来的降级兜底的方法。
Sentinel持久化规则
上面说到了Sentinel属于懒加载模式,如果不先进行访问接口,在Sentinel的可视化界面上是无法看到要访问接口的信息。下面来对Sentinel进行持久化配置,使其要访问的接口可以持久性的存在Sentinel界面上:
(一)后端yml文件:
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard地址,8080会监控8401
port: 8719 #默认为8719端口,假如被占用会自动从8719开始依次+1扫描,直到找到未被占用的端口
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: cloudalibaba-sentinel-service
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
(二) 在nacos中加入json文件
[
{
"resource": "/rateLimit/byUrl",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
详解:
resource:要做持久访问的接口路径
limitAoo:来源应用
grade:阈值类型,0表示线程数,1表示QPS
count:单机阈值
strategy:流控模式,0表示直接,1表示关联,2表示链路
controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待
cluterMode:是否集群
Nacos中的配置: