Sentinel部署、微服务使用sentinel整合springcloud alibaba、sentinel控制台详解
文章目录
控制台部署
首先需要下载控制台jar包并在本地启动
官方文档 , 下载地址,注意版本需要和maven引入的版本一致
第二步,启动
java -jar sentinel-dashboard.jar
# 这些参数 -D 是固定写法,后面再跟一些配置参数
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
其中 -Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080,默认就是8080,我们可以修改。
从 Sentinel 1.6.0 起,Sentinel 控制台引入基本的登录功能,默认用户名和密码都是 sentinel。可以参考 鉴权模块文档 配置用户名和密码。
注:若您的应用为 Spring Boot 或 Spring Cloud 应用,您可以通过 Spring 配置文件来指定配置,详情请参考 Spring Cloud Alibaba Sentinel 文档。
然后在浏览器中进行访问

用户名密码默认都是sentinel,登录进去是没有东西的,之后sentinel客户端结合使用之后就会有内容了

客户端接入控制台
-
引入坐标
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-transport-simple-http</artifactId> <version>x.y.z</version> </dependency> -
配置启动参数
启动时加入 JVM 参数
-Dcsp.sentinel.dashboard.server=consoleIp:port指定控制台地址和端口。若启动多个应用,则需要通过-Dcsp.sentinel.api.port=xxxx指定客户端监控 API 的端口(默认是 8719)。除了修改 JVM 参数,也可以通过配置文件取得同样的效果。更详细的信息可以参考 启动配置项。
优先级顺序:JVM -D 参数的优先级最高。若 properties 和 JVM 参数中有相同项的配置,以 JVM 参数配置的为准。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QAxodfzw-1658027726248)(E:\Java笔记\image\springcloud_alibaba\image-20220622223542947.png)]
服务启动成功之后,还需要请求一下接口,sentinel控制台才能有显示。也就是接下来的触发访问量
- 触发客户端初始化
确保客户端有访问量,Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包。
注意:您还需要根据您的应用类型和接入方式引入对应的 适配依赖,否则即使有访问量也不能被 Sentinel 统计。

我们现在在代码中写了一些资源的服务容错规则,所以现在这些菜单中就会有我们配置的内容,到时候和SpringCloud Alibaba整合之后,刚进来肯定是没有的,我们需要为每一个资源设置对应的规则,还有就是我们结合SpringCloud Alibaba之后,我们在控制台配置了规则之后,各个微服务重启之后,我们配置的东西也就消失了
整合SpringCloud Alibaba
第一步,引入场景启动器,这里就不需要引入上面那么多的依赖了
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
第二步,配置文件中设置控制台地址
server:
port: 8092
spring:
application:
name: order-sentinel
cloud:
sentinel:
transport:
# 设置sentinel控制台的地址
dashboard: 127.0.0.1:8080
第三步,创建rest接口,启动服务,调用测试

控制台详解
实时监控
监控接口通过的QPS 和 拒绝的QPS。
显示了每秒钟通过的QPS 、拒绝的QPS、响应时间

每一个接口都有一个实时监控界面,我们可以通过右上角进行搜索关键字

簇点链路
用来显示微服务所有可以进行设置容错规则的资源,我们也可以在此界面为各个资源设置对应的容错规则,然后再相应的菜单下就能看到了
服务中的接口如果没有使用@SentinelResource注解来指定资源名的话默认就会根据@RequestMapper注解指定的访问uri路径来命名

流控规则
流量控制(flow control) ,原理是监控应用流量的QPS或并发线程数等指标,当达到指定的阀值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保证应用的高可用。

普遍的场景:
- 在服务提供方控制脉冲流量
- 针对不同调用来源进行流控
- web接口流控
添加流控步骤:
在簇点链路菜单下,选择要进行流控的资源,然后点击右侧的流控按钮

QPS流控
QPS(Query Per Second):每秒请求树,就是服务器再一秒钟内处理了多少个请求
然后选择阀值类型并输入阀值
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TZtFb2oR-1658028041946)(E:\Java笔记\image\springcloud_alibaba\image-20220626111557135.png)]](https://i-blog.csdnimg.cn/blog_migrate/9c2e7352777eeac18f6a580ae38a9341.png)
接下来进行测试,1秒钟之内发送请求超过设定的阀值后就会被拒绝,这里是sentinel被流控之后的响应信息,如果我们想要自定义流控拒绝之后的响应信息就可以使用@SentinelResource注解
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-njt2uqls-1658028041947)(E:\Java笔记\image\springcloud_alibaba\image-20220626111741927.png)]](https://i-blog.csdnimg.cn/blog_migrate/846ea3b5be9fa51b256a05c3b34baa0f.png)
@RestController
@RequestMapping("/order")
public class OrderController {
@RequestMapping("/add")
public String add(){
System.out.println("下单成功");
return "下单成功!";
}
// value 指定资源名
@RequestMapping("/flow")
@SentinelResource(value = "flow", blockHandler = "flowBlockHandler")
public String flow(){
System.out.println("正常访问");
return "正常访问!";
}
/**
* 返回值 请求参数要和源方法一致,注意添加的是BlockException 不是BlockedException
*/
public String flowBlockHandler(BlockException e){
System.out.println("flow 流控了");
return "flow 流控了!";
}
}
然后重启服务,就会发现我们之前设置的规则都没了,没有暂时还没有持久化,我们现在需要重新为flow接口添加流控规则
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GmynQ041-1658028041951)(E:\Java笔记\image\springcloud_alibaba\image-20220626113006569.png)]](https://i-blog.csdnimg.cn/blog_migrate/72677b51949b2c96350427cd8185c134.png)
添加完流控规则后进行访问测试
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Q3s4itn-1658028041954)(E:\Java笔记\image\springcloud_alibaba\image-20220626114052577.png)]](https://i-blog.csdnimg.cn/blog_migrate/fe0a92bef65a4fec1054a403cf4a5ba3.png)
并发线程数
并发线程数控制用于保护业务线程池不被慢调用耗尽。
比如调用下游服务由于某种原因迟迟得不到响应,所有的请求都会堆积在调用方这边,也就会占用更多的线程,最终撑爆线程池,拖垮服务。
sentinel并发控制不负责创建和管理线程池,而是简单统计当前请求上下文的线程数目(正在执行的调用数目),如果超出阀值,新的请求就会立即拒绝,效果类似于信号量隔离。并发数控通常在调用端进行配置。
我们一般会使用压测,测试接口的瓶颈,然后再设置线程数的阀值,这里进行测试就暂时想阀值设置为很小。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l43o6EVo-1658028155595)(E:\Java笔记\image\springcloud_alibaba\image-20220626124637349.png)]](https://i-blog.csdnimg.cn/blog_migrate/643cc4925b197003f05b2c29325a2e43.png)
接下来进行测试,我们需要修改一下这个rest接口,不能让它请求就立刻响应,加一个睡眠几秒。
@RequestMapping("/flow")
@SentinelResource(value = "flow", blockHandler = "flowBlockHandler")
public String flow() throws InterruptedException {
TimeUnit.SECONDS.sleep(5);
System.out.println("正常访问");
return "正常访问!";
}
/**
* 返回值 请求参数要和源方法一致,注意添加的是BlockException 不是BlockedException
*/
public String flowBlockHandler(BlockException e){
System.out.println("flow 流控了");
return "flow 流控了!";
}
然后使用两个不同的浏览器访问这个接口,就能够体现出并发线程的流控了。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jyV98f9F-1658028155596)(E:\Java笔记\image\springcloud_alibaba\image-20220626114052577.png)]](https://i-blog.csdnimg.cn/blog_migrate/f963802fbc55381719bd397d45f56bac.png)
BlockException异常统一处理
在此之前,我们如果想要自定义返回结果需要通过@SentinelResource注解中的blockHandler属性来指定,如果不想在每个接口上面都使用@SentinelResource注解的话我们就可以使用BlockException来进行统一异常处理。
但是如果我们想针对不同的业务逻辑返回特定的数据的话,就还是需要使用@SentinelResource注解中的blockHandler属性来指定。
首先创建一个返回对象实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
private Integer code;
private String msg;
private T data;
public Result(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public static Result error(Integer code, String msg){
return new Result(code, msg);
}
}
定义统一异常处理
package com.hs.springcloud.exception;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hs.springcloud.domain.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Description: BlockException统一异常处理类,我们需要让该类实现BlockExceptionHandler接口,并且被spring容器管理
* @Author 胡尚
* @Date: 2022/6/26 15:55
* @Version 1.0
*/
@Component
@Slf4j
public class MyBlockException implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
// 根据最后一个参数BlockException来判断数据哪一种容错规则了
// getRule()会包含一些资源信息、规则的详细信息
log.info("BlockExceptionHandler BlockException================={}", e.getRule());
Result result = null;
if (e instanceof FlowException){
result = Result.error(500, "接口限流了");
}else if (e instanceof DegradeException){
result = Result.error(500, "服务降级了");
}else if (e instanceof ParamFlowException){
result = Result.error(500, "热点参数限流了");
}else if (e instanceof SystemBlockException){
result = Result.error(500, "触发系统保护规则了");
}else if (e instanceof AuthorityException){
result = Result.error(500, "授权规则不通过");
}
// 返回json数据
httpServletResponse.setStatus(500);
httpServletResponse.setCharacterEncoding("utf-8");
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
new ObjectMapper().writeValue(httpServletResponse.getWriter(), result);
}
}
最后进行测试,首先将原来flow接口上面的@SentinelResource注解删掉,测试统一的异常处理
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NyPq3Tun-1658028207680)(E:\Java笔记\image\springcloud_alibaba\image-20220626162427863.png)]](https://i-blog.csdnimg.cn/blog_migrate/804787f89fde7df079c586b96ece1d4a.png)
如果需要针对不同的接口去做不同的业务逻辑处理的话,还是需要使用@SentinelResource注解来指定
流控模式
流控规则中还有一些高级选项
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M6v0LiVU-1658028255257)(E:\Java笔记\image\springcloud_alibaba\image-20220626163003760.png)]](https://i-blog.csdnimg.cn/blog_migrate/80bb54cbdbbe7dded41cd911029a2ca6.png)
这里有三种流控模式:直接、关联、链路
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NsKjNLbL-1658028255258)(E:\Java笔记\image\springcloud_alibaba\image-20220626165507567.png)]](https://i-blog.csdnimg.cn/blog_migrate/cdaf9fb25d31a9369e4a19789097885c.png)
直接
默认的流控模式,之前使用的都是直接流控模式
直接流控模式:我们对某个资源设置流控规则,一旦流量超过指定的阀值之后受影响而限制的资源也就是它本身。
关联
当关联资源达到阀值后,对当前资源流控。
当两个资源之间具有资源争抢或者依赖关系的时候,这两个资源便具有了关联。比如对数据库同一个字段的读操作和写操作存在争抢,读的速度过高会影响写的速度,写的速度过高会影响读的速度。如果放任读写操作争抢资源,则争抢本身带来的开销会降低整体的吞吐量。
可以使用关联限流来避免具有关联关系的资源之间过度的争抢

关联流控模式:一旦/order/add的流量超过了这里设置的阀值,受影响而限制的是/order/flow资源
链路
链路流控模式:这里主要是有一个调用链路,它是根据这个调用链路来进行流控的。
下图中记录了资源之间的调用链路,这些资源通过调用关系,相互之间构成一颗调用树,这里有一个test1接口和test2接口,他们都调用了getUser资源。Sentinel允许只根据某个入口的统计信息对资源限流。
我们需要明确一点,sentinel不仅仅可以针对接口解析流控,还可以针对业务方法进行流控
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ogzDTCmE-1658028255265)(E:\Java笔记\image\springcloud_alibaba\image-20220627124651427.png)]](https://i-blog.csdnimg.cn/blog_migrate/430e0473575e4e60c563e72ee9e1de20.png)
创建一个service接口
@Service
public class UserServiceImpl implements UserService {
@SentinelResource(value = "getUser")
@Override
public User getUser() {
return new User("hushang");
}
}
然后在controller中创建两个接口调用getUser()方法
@RequestMapping("/test1")
public User test1() {
return userService.getUser();
}
@RequestMapping("/test2")
public User test2() {
return userService.getUser();
}
接下来再控制台设置流控规则
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PL5G0B0m-1658028255266)(E:\Java笔记\image\springcloud_alibaba\image-20220627130948141.png)]](https://i-blog.csdnimg.cn/blog_migrate/494ab8fe538ca5fd444cc7059c03ba3e.png)
问题一:
配置完后,我们会发现链路规则不生效,原因如下:
从1.6.3版本开始,Sentinel Web filter默认收敛所有URL的入口context,因此链路限流不生效。
1.7.0版本开始(对应SCA的2.1.1.RELEASE) , 官方在CommonFilter引入了web-context-unify参数,用来控制支付收敛context,将其设置为false即可根据不同的URL进行链路限流
# 设置为false使链路限流生效,默认将调用链路收敛了
spring.cloud.sentinel.web-context-unify=false
问题二:
此场景拦截不到BlockException,因为我们一旦使用了@SentinelResource注解就不会去运用统一异常处理了 所以我们只能在@SentinelResource注解中使用blockHandler属性来指定,不然就直接抛异常到页面上面了
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ue1tchA9-1658028255267)(E:\Java笔记\image\springcloud_alibaba\image-20220627154250038.png)]](https://i-blog.csdnimg.cn/blog_migrate/fd3e95b11bb04f7d686472898d0ba017.png)
所以我们需要在service层来指定
@Service
public class UserServiceImpl implements UserService {
@SentinelResource(value = "getUser", blockHandler = "getUserBlockHandler")
@Override
public User getUser() {
return new User("hushang");
}
/**
* 这里的最后一个参数BlockException 是一定要加的
*/
public User getUserBlockHandler(BlockException e) {
return new User("userService 被限流了");
}
}
重启服务,重新在控制台配置限流规则,然后进行测试
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MQHHP0UY-1658028255268)(E:\Java笔记\image\springcloud_alibaba\image-20220627154524050.png)]](https://i-blog.csdnimg.cn/blog_migrate/bc579167e1c09a5bfd08dd65a1026337.png)
流控效果
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rd5tAZ6i-1658028521971)(E:\Java笔记\image\springcloud_alibaba\image-20220627155826835.png)]](https://i-blog.csdnimg.cn/blog_migrate/c24415fd87bed34d3f9583206b56b89e.png)
当 QPS 超过某个阈值的时候,则采取措施进行流量控制。线程数是没有流控效果的。
流量控制的效果包括以下几种:直接拒绝、Warm Up、排队等待。对应代码开发中 FlowRule 中的 controlBehavior 字段。
快速失败(RuleConstant.CONTROL_BEHAVIOR_DEFAULT)方式是默认的流量控制方式,当QPS超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException。这种方式适用于对系统处理能力确切已知的情况下,比如通过压测确定了系统的准确水位时。
Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。处理激增流量,当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。
冷加载因子:codeFactor 默认是3,也就是刚开始放行的请求数 = QPS阀值 / 3 , 然后再看看递增,逐渐提升至设定的QPS阀值
通常冷启动的过程系统允许通过的 QPS 曲线如下图所示:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h7TWPgys-1658028521974)(E:\Java笔记\image\springcloud_alibaba\68292392-b5b0aa00-00c6-11ea-86e1-ecacff8aab51.png)]](https://i-blog.csdnimg.cn/blog_migrate/d65c67463ba9e3fb6e9cfa96d1e7805a.png)
如下图所示,我设置一个预热时长为7秒,它不会一瞬间接收20个请求,它会慢慢的接收,可能刚开始第一秒只能接收3个,可能第二秒最多只能接收5,就这样在我们设定的预热时长内慢慢的增加,当7秒后才会每秒接收20的请求,
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pFMxjw6O-1658028521977)(E:\Java笔记\image\springcloud_alibaba\image-20220627162438712.png)]](https://i-blog.csdnimg.cn/blog_migrate/28bd5f5c70d2cc37a33e5744d8a86033.png)
使用场景就比如电商项目的秒杀场景,如果刚开始一万个请求直接访问,这个时候缓存中也没有数据,这么多请求就直接落到了数据库中,把数据库弄宕机了,这也就是缓存击穿。这种情况就可以使用warm up,先放一些请求进来,去访问数据库,然后将查询的数据存入缓存中,在放更多的请求进来,之后的请求就可以去缓存中获取数据,这就可以避免激增流量瞬间打垮冷系统。这只是冷系统中的一种例子。
案例:
设置下图所示,5秒后才会每秒接收10个请求
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KcL3hkjM-1658028521978)(E:\Java笔记\image\springcloud_alibaba\image-20220627194158015.png)]](https://i-blog.csdnimg.cn/blog_migrate/ab8c3e5f094ca55e1669bd833defca8e.png)
然后每秒发送10个请求,结果如下
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1NW5ixEw-1658028521979)(E:\Java笔记\image\springcloud_alibaba\image-20220627194937686.png)]](https://i-blog.csdnimg.cn/blog_migrate/770e89b999dd9354250527a94bc455d5.png)
排队等待(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。处理脉冲流量,详细文档可以参考 流量控制 - 匀速器模式,具体的例子可以参见 PaceFlowDemo。
该方式的作用如下图所示:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dwJCruqL-1658028521980)(E:\Java笔记\image\springcloud_alibaba\68292442-d4af3c00-00c6-11ea-8251-d0977366d9b4.png)]](https://i-blog.csdnimg.cn/blog_migrate/96e87381ed433a5e98a936a08f755621.png)
这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。
注意:匀速排队模式暂时不支持 QPS > 1000 的场景。
如下图所示,QPS的阀值是10,如果一秒钟之内有25个请求,剩下的15个请求B不会立刻失败掉,而是会等待5秒,在我们指定是超时时间中处理10个请求A,然后再来处理多余的15个请求B。
5秒钟之内处理10的请求A,处理完一个请求A就来处理请求B,如果在规定的5秒内,10的请求A都还没有处理完,那么15个请求B就直接拒绝掉,就和上厕所一样,总共只有10个坑,出来一个人就进去一个人,在外面等待的人最多只能等待5秒。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VvBz7gr8-1658028521981)(E:\Java笔记\image\springcloud_alibaba\image-20220627190433699.png)]](https://i-blog.csdnimg.cn/blog_migrate/189b7e5c583a0f0c9f9359042aa860e5.png)
下图是快速失败和排队等待的区别:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nM9WXZkW-1658028521982)(E:\Java笔记\image\springcloud_alibaba\image-20220627200727227.png)]](https://i-blog.csdnimg.cn/blog_migrate/739ce5593e8e08aff38f5a76690e398c.png)
熔断降级规则
熔断降级通常在服务消费方进行配置。
熔断策略:
- 慢调用比例 (
SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。 - 异常比例 (
ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是[0.0, 1.0],代表 0% - 100%。 - 异常数 (
ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
触发熔断后的处理措施:
- 提供fallback实现,也就是服务降级
- 返回错误result
- 读缓存(DB访问降级)
熔断降级规则(DegradeRule)包含下面几个重要的属性:
| Field | 说明 | 默认值 |
|---|---|---|
| resource | 资源名,即规则的作用对象 | |
| grade | 熔断策略,支持慢调用比例/异常比例/异常数策略 | 慢调用比例 |
| count | 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值 | |
| timeWindow | 熔断时长,单位为 s | |
| minRequestAmount | 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入) | 5 |
| statIntervalMs | 统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入) | 1000 ms |
| slowRatioThreshold | 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入) |
接下来使用控制台的图片来介绍熔断策略
首先是慢调用比例
单位时间statIntervalMs默认是1000ms,在控制台没有设置这个值的窗口,但是代码方式可以设置。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mhkc98Yl-1658028780561)(E:\Java笔记\image\springcloud_alibaba\image-20220627205852791.png)]](https://i-blog.csdnimg.cn/blog_migrate/d830c95fed501fed3d05ea2f1209940c.png)
异常比例:
在单位时间内,最少发送5次请求,如果这其中出现异常的比例大于了0.4就会触发熔断10s。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-owoOZnOP-1658028780562)(E:\Java笔记\image\springcloud_alibaba\image-20220627211757372.png)]](https://i-blog.csdnimg.cn/blog_migrate/706ca31e516ce099c7ad4b39766bb7bd.png)
结果如下:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SQKA3kll-1658028780567)(E:\Java笔记\image\springcloud_alibaba\image-20220627212024435.png)]](https://i-blog.csdnimg.cn/blog_migrate/66e530e7385ea9711e946018669fc4c7.png)
异常数
单位时间内,发送8次请求,如果其中出现了超过5次异常就触发熔断
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qWmt1B0E-1658028780568)(E:\Java笔记\image\springcloud_alibaba\image-20220627212213215.png)]](https://i-blog.csdnimg.cn/blog_migrate/694dde428aec7b89d4ee896cbff6ba4d.png)
整合OpenFeign进行降级
服务消费方调用服务提供方的时候,如果服务提供者发生了异常,会把异常传播给服务消费方,我们这个时候就可以对服务提供方进行熔断降级的处理 ,去调用降级的方法。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SwdZJSjg-1658028897180)(E:\Java笔记\image\springcloud_alibaba\image-20220627212902941.png)]](https://i-blog.csdnimg.cn/blog_migrate/59dd0c670ebf650f0b8a6ab61acdce98.png)
我们使用openfeign的话,还需要启动nacos注册中心
服务提供方:
@RestController
@RequestMapping("/stock")
public class StockController {
// 这里创建一个接口,并且每次调用都抛出异常,然后启动该服务
@RequestMapping("/reduce2")
public String reduce2(){
int i = 1/0;
return "库存减少!";
}
}
服务消费方:
第一步:首先导入maven坐标
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--nacos的服务注册与发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- OpenFeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
</dependencies>
第二步,yml配置文件编写
server:
port: 8093
spring:
application:
name: order-service
cloud:
# nacos相关配置
nacos:
server-addr: 127.0.0.1:8848
discovery:
username: nacos
password: nacos
namespace: public
# 添加feign对sentinel的支持
feign:
sentinel:
enabled: true
第三步,创建Feign的调用接口
// 这里要使用fallback属性来指定下一步创建降级的类
@FeignClient(name = "stock-service", path = "/stock", fallback = StockFeignServiceFallback.class)
public interface StockFeignService {
@RequestMapping("/reduce2")
String reduce2();
}
第四步,创建OpenFeign的降级的类,这个类必须去实现上一步中Feign的调用接口,并注入到spring容器中
@Component
public class StockFeignServiceFallback implements StockFeignService{
@Override
public String reduce2() {
return "降级了,进入兜底方法了!";
}
}
第五步,编写controller接口并进行测试
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private StockFeignService stockFeignService;
@RequestMapping("/add")
public String add(){
String msg = stockFeignService.reduce2();
return "下单成功!" + msg;
}
}
最后进行测试,之前不加降级的兜底方法的话这里会直接抛异常,现在会执行降级方法
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zVXr0tJY-1658028897183)(E:\Java笔记\image\springcloud_alibaba\image-20220627221307298.png)]](https://i-blog.csdnimg.cn/blog_migrate/f36ce9ba99fd3a4a710951b35d1f8486.png)
热点规则
热点即经常访问的数据,很多时我们希望统计某个热点数据中访问频次最高的数据,并对其访问进行限制,就可以使用热点规则
如下所示,可能id=1或id=2的访问量比较大,id为其他值的时候访问量比较平缓,这个时候我们就可以针对id=1或id=2的时候来进行流控
@RequestMapping("/get/{id}")
public String getById(@PathVariable("id") Integer id){
System.out.println("通过id获取数据");
return "正常 通过id获取数据";
}
常用场景:
- 热点商品访问/操作控制
- 用户/ip 防刷
接下来我们实际实现一下
创建一个接口
@RequestMapping("/get/{id}")
@SentinelResource(value = "getById", blockHandler = "getByIdBlockHandler")
public String getById(@PathVariable("id") Integer id){
System.out.println("通过id获取数据");
return "正常 通过id获取数据";
}
public String getByIdBlockHandler(@PathVariable("id") Integer id, BlockException e){
System.out.println("通过id获取数据,热点异常处理");
return "热点异常处理";
}
然后启动服务,sentinel控制台中设置规则的界面如下
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-epUomqrC-1658029143968)(E:\Java笔记\image\springcloud_alibaba\image-20220628125203798.png)]](https://i-blog.csdnimg.cn/blog_migrate/a467ca63f8504edc9d28916bac4e0c65.png)
-
参数索引
就是我们要进行热点流控的参数,是接口中的第几个参数,也就是rest接口形参的位置,索引是从0开始的。
-
单机阈值
这个阈值主要是针对第二行的QPS来进行设置的,这里首先是对这个参数id 设置一个全局的阈值,也就是不管id等于多少,都先设置一个公共的阈值,点击新增按钮后,在根据id具体的值来设置具体的阈值。
这里有两种填写情况
- 参数的值大部分都是热点参数,那这里的单机阈值就主要是针对热点参数进行流控,然后再额外添加针对普通参数值进行流控
- 参数的值大部分都是普通数据,只有少部分的热点参数,那么这里主要就是针对普通参数进行流控,然后在额外添加针对热点参数值进行流控
-
统计窗口时长
QPS一般都是每秒的访问数据,这里是设置统计几秒中的QPS
点击新增按钮之后,如果想为参数特定的值来设置阈值的步骤如下:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Uy0o9J1-1658029143969)(E:\Java笔记\image\springcloud_alibaba\image-20220628183439940.png)]](https://i-blog.csdnimg.cn/blog_migrate/830446f2b22a3201cbd9c5a6c183af78.png)
为特定的值设置阈值
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m6BbwGE9-1658029143973)(E:\Java笔记\image\springcloud_alibaba\image-20220628184433259.png)]](https://i-blog.csdnimg.cn/blog_migrate/af83b88bb131c1c95fa80d24f5877984.png)
添加完成之后记得在点击一些编辑按钮,查看一下我们刚刚添加的是否存在,我刚刚就是没有生效,然后添加了多个规则,然后删除,才生效
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4776JFKU-1658029143975)(E:\Java笔记\image\springcloud_alibaba\image-20220628184724936.png)]](https://i-blog.csdnimg.cn/blog_migrate/e9e8cce879266e6c9c58d031e152724d.png)
然后进行测试
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CvFvNTfH-1658029143976)(E:\Java笔记\image\springcloud_alibaba\image-20220628184827574.png)]](https://i-blog.csdnimg.cn/blog_migrate/2fd6807508e50806f2670242b025e706.png)
系统规则
在线上环境中,可能会有很多不可预知的一些因素来威胁系统的稳定性。比如:
- 容量评估不到位,某个大流量接口限流配置不合理或没有配置限流,导致系统崩溃,来不及处理。
- 忽然发现服务器的Load 和 CPU usage等开始飙高,但却没有办法很快的确认到是什么原图造成的,也里阿布吉处理
- 当其中一台服务器挂了之后,本该由这台服务器处理的流量被负载均衡到其他服务器上,另外的服务器也被打挂了,导致服务雪崩。
- 希望有个全局的兜底防护,即使缺乏容量评估也希望有一定的保护机制
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-10QqOquW-1658029230512)(E:\Java笔记\image\springcloud_alibaba\image-20220628191347330.png)]](https://i-blog.csdnimg.cn/blog_migrate/28a70e4248e190748a70b3009c866a22.png)
控制台界面如下:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M5g82rPF-1658029230513)(E:\Java笔记\image\springcloud_alibaba\image-20220628191529064.png)]](https://i-blog.csdnimg.cn/blog_migrate/4e0ba0fccded2030e1b2d4ef9e79de1a.png)
注意系统规则只针对入口资源(EntryType=IN)生效。
- Load自适应,仅对linux/Unix-like机器生效,系统的load1作为启发指标,进行自适应系统保护。当系统load1超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR阶段)。系统容量由系统
maxQPS * minQPS估算得出。设定参考值一般是CPU cores * 2.5 - CPU usage(1.5.0+版本):当系统CPU使用率超过阈值即触发系统保护,取值范围为0.0~1.0,比较灵敏
- 平均RT:当单台机器上所有入口流量的平均响应时间达到阈值即触发系统保护,
- 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护,这并不是一个接口的并发数超过阈值就触发,而是系统所有访问接口的平均值
- 入口QPS:当单台机器上所有入口流量的QPS达到阈值即触发系统保护,这里也是求所有接口的qps平均值
CPU使用率
如果cpu的使用率大于了10%,就会触发系统保护规则

此时我本机的cpu使用率超过了这个阈值,现在访问任何接口都会报错
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K4Ch4876-1658029230520)(E:\Java笔记\image\springcloud_alibaba\image-20220628191846684.png)]](https://i-blog.csdnimg.cn/blog_migrate/7f2e7092c515a8d6f2e277337a5655ad.png)
更多推荐
所有评论(0)