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: 8401spring:application:name: cloudalibaba-sentinel-servicecloud:nacos:discovery:server-addr: localhost:8848 #Nacos服务注册中心地址sentinel:transport:dashboard: localhost:8080 #配置Sentinel dashboard地址,8080会监控8401port: 8719 #默认为8719端口,假如被占用会自动从8719开始依次+1扫描,直到找到未被占用的端口datasource:ds1:nacos:server-addr: localhost:8848dataId: cloudalibaba-sentinel-servicegroupId: DEFAULT_GROUPdata-type: jsonrule-type: flowmanagement: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-servicecloud:nacos:discovery:server-addr: localhost:8848 #Nacos服务注册中心地址sentinel:transport:dashboard: localhost:8080 #配置Sentinel dashboard地址,8080会监控8401port: 8719 #默认为8719端口,假如被占用会自动从8719开始依次+1扫描,直到找到未被占用的端口datasource:ds1:nacos:server-addr: localhost:8848dataId: cloudalibaba-sentinel-servicegroupId: DEFAULT_GROUPdata-type: jsonrule-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中的配置: