前言
微服务保护学习笔记(一)雪崩问题及解决方案、Sentinel介绍与安装
2 流量控制
雪崩问题有四种解决方案,其中流量控制是避免服务因突发的流量而发生故障,是对微服务雪崩问题的预防。
2.1 簇点链路
当请求进入微服务时,首先会访问DispatcherServlet
,然后进入Controller
、Service
、Mapper
,这样的一个调用链就叫做簇点链路。簇点链路中被监控的每一个接口就是一个资源。
默认情况下,Sentinel会监控SpringMVC的每一个端点(Endpoint,也就是Controller
中的方法),因此SpringMVC的每一个端点就是调用链路中的一个资源。
例如,调用sd-user-service微服务中的UserController
中的端点:/user/now
。
如上图所示,在操作区有4个选项,分别是:
- 流控:流量控制
- 降级:降级熔断
- 热点:热点参数限流,是限流的一种
- 授权:请求的权限控制
2.2 流控操作
点击操作区的“流控”按钮,弹出“新增流控规则”表单:
阈值类型的含义是限制/user/now
这个资源的单机QPS为1,即每秒只允许1次请求,超出的请求会被拦截并报错。
例如有以下需求:给/user/now
这个资源设置流控规则,QPS不能超过5。
- 1)首先在Sentinel控制台添加限流规则:
- 2)利用jmeter工具测试,创建一个测试案例,参数如下:
- 3)启动测试,查看结果树
2.3 流控模式
在“新增流控规则”时,点击“高级选项”,可以选择三种流控模式:
- 直接:统计当前资源的请求,触发阈值时对当前资源直接限流,也是默认的模式;
- 关联:统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流;
- 链路:统计从指定链路访问到本资源的请求,触发阈值时,对指定链路限流。
2.3.1 关联模式
关联模式是统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流。
例如,有两个有竞争关系的资源(/user/update
资源和/user/query
资源),且/user/update
资源优先级较高,/user/query
资源优先级较低时,就可以采用关联模式对/user/query
资源进行限流。
下面对关联模式进行测试:
- 1)定义
/user/update
资源和/user/query
资源
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/query")
public String query() {
return "查询用户成功";
}
@GetMapping("/update")
public String update() {
return "更新用户成功";
}
}
- 2)重启微服务,查看Sentinel控制台的簇点链路
- 3)配置流控规则
对哪个资源限流,就点击哪个资源后面的“流控”按钮。这里是对用户查询/user/query
资源限流,因此点击/user/query
资源后面的“流控”按钮:
- 4)使用jmeter工具测试
- 5)启动测试,10s内在浏览器访问
http://127.0.0.1:8081/user/query
2.3.2 链路模式
链路模式是指统计从指定链路访问到本资源的请求,触发阈值时,对指定链路进行限流。
假设有如下场景:/user/query
资源和/user/update
资源都需要调用Service层的同一方法queryUser()
,则存在以下两条链路:
- 链路一:
/user/query
→queryUser()
- 链路二:
/user/update
→queryUser()
使用链路模式则可以对任意链路进行限流。
下面对链路模式进行测试:
- 1)在sd-user-service微服务中创建Service层的
queryUser()
方法
默认情况下,UserService
中的方法是不被Sentinel监控的,需要自己通过注解来标记要监控的方法。 给UserService
的queryUser()
方法添加@SentinelResource
注解:
@Service
public class UserService {
@SentinelResource("queryUser")
public String queryUser() {
return "Service层查询用户信息";
}
}
- 2)修改
UserController
中的query()
和update()
方法,使他们都调用UserService
的queryUser()
方法
// com.hsgx.user.controller.UserController
@Autowired
private UserService userService;
@GetMapping("/query")
public String query() {
userService.queryUser();
return "查询用户成功";
}
@GetMapping("/update")
public String update() {
userService.queryUser();
return "更新用户成功";
}
- 3)在链路模式中,是对不同来源的两个链路做监控。但是Sentinel默认会给进入SpringMVC的所有请求设置同一个root资源,因此会导致链路模式失效。为此,需要关闭这种对SpringMVC的资源聚合,修改sd-user-service微服务的application.yml文件:
spring:
cloud:
sentinel:
web-context-unify: false # 关闭context整合
- 4)重启微服务,可以看到Sentinel控制台中,出现了新的
queryUser
资源:
- 5)点击
/user/query
资源下的queryUser
资源后面的“流控”按钮,填写流控规则:
- 6)使用jmeter工具测试
- 7)测试
/user/query
资源
可见,/user/query
资源只有2个请求能通过。
- 8)测试
/user/update
资源
可见,/user/update
资源完全不受影响。
…
本节完,更多内容请查阅分类专栏:微服务学习笔记
感兴趣的读者还可以查阅我的另外几个专栏: