sentinel 服务保护(限流、熔断降级)
主要根据资源和规则进行约束保护:
资源:
-
主流框架(web servlet\dubbo\spring cloud\reactor...)web接口
-
编程式接口:SphU API
-
声明式接口:@SentinelResource
规则:
-
流量控制:比如每一秒钟能够接收多少的请求
-
熔断降级:防止雪崩的
-
系统保护:根据CPU,RAM等的繁忙都
-
来源访问控制:可以避免同一个IP地址来爬虫
-
热点参数:对指定的资源进行控制,比如不是会员的不能够免费浏览小说资源
工作流程
1、sentinel整合
添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
安装可视化界面
docker run -d --name sentinel-dashboard -p 9898:8858 bladex/sentinel-dashboard:1.8.7
在配置文件中配置sentinel可视化dashboard
# 配置sentinel
sentinel:
transport:
# 可视化界面的IP地址和端口号
dashboard: 10.0.0.100:9898
# 默认是懒加载,即调用的时候才在可视化中显示,现在要一启动就加载
eager: true
在响应的类中标注资源类,当然,如果是controller中可以不用主动添加,因为sentinel默认接管web的接口
- 添加注解@SentinelResource(value = "资源名称")
值得注意的是:
Q:使用docker部署时,在簇点中查看不到消息,是因为sentinel与应用不在同一个局域网内,因此无论怎么发送都监测不到。
A:解决办法:在相应的配置文件中配置sentinel.transport.clientIP:写下当前运行代码的主机地址即可
Q:修改了之后,实时监控和簇链链路等页面没有数据 A:没有数据是因为没有流量,可以尝试着发送请求产生流量,比如获取所有歌曲,/song/getAll
(这是我微服务的其中一个接口,得根据实际的接口来),一段时间没有流量了,实时监控的数据也就会清空,但是簇点链路会存在的
2、Sentinel的异常处理
BlockException异常的出现一般由一下几类
-
web 接口,即Controller层
-
@SentinelResource 自定义的监控层,比如在接口的实现方法层
-
OpenFeign 远程调用层,比如找不到微服务,或者QPS被限制访问等
-
sphu 自定义监控, 使用try-catch
2.1、web接口异常的处理(自定义处理)
// 实现阻塞异常接口,专门处理SpringMVC的异常
@Component
public class webMVCBlockException implements BlockExceptionHandler {
// 用于对象转json字符串
@Resource
private ObjectMapper objectMapper;
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, String s, BlockException e) throws Exception {
// 设置响应类型和响应字符编码
httpServletResponse.setContentType("application/json;charset=utf-8");
// 获取响应写入器
PrintWriter writer = httpServletResponse.getWriter();
// 编辑错误信息
String error = httpServletRequest.getRequestURI().toString() + "-被Sentinel限制了,原因是:" + e.getMessage();
// 封装错误信息
Result result = Result.fail().setMsg(error);
// 转为json字符串
String resError = objectMapper.writeValueAsString(result);
// 写入器写入响应
writer.write(resError);
// 刷入
writer.flush();
// 关闭
writer.close();
}
}
注意:默认下规则是存储到内存当中,如果重启应用之后会规则就没了。
2.2、@SentinelResource资源的异常处理
一般标注在非controller层,比如service层
使用的是切面的方式来进行监控
-
如果在@SentinelResource中有标注BlockHandler,则根据BlockHandler来进行处理,这个需要自定义实现(1)
-
如果没有标注BlockHandler,但又标注fallback,则按照fallback来进行处理,这个需要自定义(2)
-
如果连fallback都没有标注,则会调用defaultFallback进行处理,这个也是需要自定义(3)
-
如果defaultFallback也没有标注,则抛出异常(4),抛给springboot,可以使用全局异常处理器来处理
//原来的要监控的方法,指定blockHandler方法
@SentinelResource(value="createOrderService",blockHandler="createOrderBlockHandler")
public Order createOrder(String userId, String productId, int number){
// 正常走这里,违反规则走下面
}
// 需要添加多一个参数 BlockException e
public Order createOrderBlockHandler(String userId, String productId, int number, BlockException e){
// 进行异常处理,比如返回假数据
Order order = new Order("1", userId, null, null, 0);
order.setAddress("出现异常:"+e.getMessage());
return order;
}
注意,@SentinelResource一般使用在非controller层,因为controller层默认就被监控的
2.3、openfeign异常处理
可参考openfeign篇的第9小结
3、流控规则
以下是簇点链路示例
-
/create 为Controller层的API接口
-
createOrder 为service层的实现方法
-
GET xxxx 为openfeign远程调用的接口
以下是sentinel的流控面板
-
阈值类型,
-
QPS 每秒的请求数量,比如每秒通过一个请求,通过计数器来进行统计限制
-
并发线程数,要配合线程池,统计线程数量来进行限制,由于存在线程切换等因素,效率没有QPS那么高
-
-
是否集群
-
单机均摊,即每个相同的微服务可处理一个请求,比如有3个订单微服务,那每一个微服务在1秒中可处理一个请求
-
总体阈值,所有相同的微服务只能处理一个请求,比如有3个订单微服务,那三个微服务只能有一个来处理一个请求
-
高级选项
-
流控模式
-
直接,直接对资源进行限制
-
关联,对于又读又写的资源,为了保证某个优先,比如写优先,则设置限制读的流量,增大写的流量,保证数据的一致性
-
链路(入口),对链路的入口接口进行显示,比如创建订单,可以通过普通的接口来创建,也可通过秒杀的接口来创建,当活动开始的时候,秒杀的接口会涌入较大的流量,为了避免服务的崩溃,对创建订单来进行限制,但是普通的接口不限制,则需要选择链路的入口进行限制,也就是秒杀入口
-
链路示例:
需要在配置文件中配置为不同的上下文
spring:
cloud:
sentinel:
# 链路策略需要配置不同的上下文,默认情况下是同一个上下文
# 默认为true,都属于同一个sentinel-spring-web-context
web-context-unify: false
效果
对createOrder进行限制
流控效果:
-
快速失败,违反规则直接走兜底回调
-
warm up,逐步增加处理能力,知道设置的阈值,QPS为最大值,预热时长,比如3个QPS,时间为3秒,1秒时只接受1个,2秒时两个,3秒后达到最大值3个,之后都是3个,直到每秒的请求小于3个才开始下降
-
排队等待,就排队嘛,比如QPS为2,设置一个超时时间20秒,那么每一秒请求能处理2个,之后的排队,如果请求的时间大于超时时间,则被丢弃
4、熔断降级
示例背景:当G调用D发现D处理超时,在默认情况下,G会一直等到D处理完成或者处理异常之后才能得到返回结果,但是D处理超时,就会产生积压,倒是服务雪崩。
因此需要G主动处理结果。
熔断降级一般用于远程调用端
原理
慢调用比例:根据调用返回结果的快慢进行判断,超过一定比例则断开
比如
-
最大RT :最大响应时间为1秒,每次请求最大的响应时间为1s,即1秒内就要获取请求结果
-
比例阈值:0.8,
-
熔断时长:10 每10秒发送探测
-
最小请求数:5,当请求超过5个时开始统计
-
统计时长:5秒内
在5秒内发送大量的请求,只要响应的时间在1秒内的请求都表示成功,如果80%的响应时间都超过1秒,则开启熔断,根据熔断时长时间内不再发送请求而是走兜底回调,超过熔断时长时发送探测请求
异常比例
根据出现异常的比例来进行熔断
异常数
5、热点规则
比前两个更细致的限制,比如对带有特定参数的请求进行控制
使用场景:
1、对于下架的商品下单进行控制,即不允许访问
2、对于用户是否是VIP进行选择性控制,是VIP则不进行限购,不是VIP限购等等
3、每个用户秒杀的QPS不超过1