专栏目录
0.docker快速入门
1.初识微服务
2.Gateway网关路由
3.Nacos配置管理
4.Sentinel微服务保护
文章目录
微服务保护
处理业务时,微服务只见相互调用过程中,存在一些问题:
首先是业务健壮性问题:
例如在之前的查询购物车列表业务中,购物车服务需要查询最新的商品信息,与购物车数据做对比,提醒用户。大家设想一下,如果商品服务查询时发生故障,查询购物车列表在调用商品服务时,是不是也会异常?从而导致购物车查询失败。但从业务角度来说,为了提升用户体验,即便是商品查询失败,购物车列表也应该正确展示出来,哪怕是不包含最新的商品信息。
还有级联失败问题:
还是查询购物车的业务,假如商品服务业务并发较高,占用过多Tomcat连接。可能会导致商品服务的所有接口响应时间增加,延迟变高,甚至是长时间阻塞直至查询失败。
此时查询购物车业务需要查询并等待商品查询结果,从而导致查询购物车列表业务的响应时间也变长,甚至也阻塞直至无法访问。而此时如果查询购物车的请求较多,可能导致购物车服务的Tomcat连接占用较多,所有接口的响应时间都会增加,整个服务性能很差, 甚至不可用。
1. 服务保护方案
1.1 请求限流
该方案解决的是由于并发过高引起的服务故障,通过该方案将限制或控制接口访问的并发流量,避免服务因流量激增而出现故障。
请求限流往往会有一个限流器,数量高低起伏的并发请求曲线,经过限流器就变的非常平稳。
这就像是水电站的大坝,起到蓄水的作用,可以通过开关控制水流出的大小,让下游水流始终维持在一个平稳的量。
1.2 线程隔离
务接口响应时间长,而且并发高时,就可能耗尽服务器的线程资源,导致服务内的其它接口受到影响。
为了避免某个接口故障或压力过大导致整个服务不可用,我们可以限定每个接口可以使用的资源范围,也就是将其“隔离”起来。
简单说就是将蛋糕切成多块,即使一块弄脏了,其他的还能吃,而不是整块弄脏都吃不了了。
1.3 服务熔断
线程隔离虽然避免了雪崩问题,但故障服务依然会拖慢接口响应速度。而且故障依然会导致功能出现故障,使得业务不可用所以,我们要做两件事情:
- 编写服务降级逻辑:就是服务调用失败后的处理逻辑,根据业务场景,可以抛出异常,也可以返回友好提示或默认数据。
- 异常统计和熔断:统计服务提供方的异常比例,当比例过高表明该接口会影响到其它服务,应该拒绝调用该接口,而是直接走降级逻辑。
1.4 总结
降级处理就是为了在服务接口出错等情况下,不让其进行异常报错,提高用户的体验。
服务熔断就是通过编写逻辑判断接口何时进行降级处理,并在降级处理后何时进行恢复从而再次被调用,以此来提高服务接口的响应时间。
2. Sentinel框架
Sentinel是阿里巴巴开源的一款服务保护框架。
Sentinel 的使用可以分为两个部分:
- 核心库(Jar包):不依赖任何框架/库,能够运行于 Java 8 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。在项目中引入依赖即可实现服务限流、隔离、熔断等功能。
- 控制台(Dashboard):Dashboard 主要负责管理推送规则、监控、管理机器信息等
2.1 相关网站
服务启动后的控制台网址:http://localhost:8090
账号和密码,默认都是:sentinel
2.2 快速入门
①引入依赖
<!--sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
②配置控制台
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8090
③启动后在进行服务接口访问时,sentinel客户端就会将服务访问的信息提交到控制台并展示
2.3 优化
默认情况下Sentinel会把路径作为簇点资源的名称,无法区分路径相同但请求方式不同的接口,查询、删除、修改等都被识别为一个簇点资源,因此可以选择打开Sentinel的请求方式前缀,把请求方式 + 请求路径
作为簇点资源名
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8090
http-method-specify: true # 开启请求方式前缀
3. 请求限流
直接使用控制台在簇点链路的操作区域选择流控
对齐进行限流
4. 线程隔离
使用OpenFeign整和Sentinel
①在相关服务的application文件中开启feign的sentinel功能
feign:
sentinel:
enabled: true # 开启feign对sentinel的支持
②重启服务即可
③使用控制台在FeignClient对应的簇点链路的操作区域选择流控
④阈值选择并发线程数
5. 服务熔断
5.1 编写降级处理逻辑
以OpenFeign的FeignClient编写失败,使用FallbackFactory进行处理为例:
- FallbackClass,无法对远程调用的异常做处理
- FallbackFactory,可以对远程调用的异常做处理
①在相关模块中定义FallbackFactory并实现
import ...;
@Slf4j
public class ItemClientFallback implements FallbackFactory<ItemClient> {
@Override
public ItemClient create(Throwable cause) {
return new ItemClient() {
@Override
public List<ItemDTO> queryItemByIds(Collection<Long> ids) {
log.error("远程调用ItemClient#queryItemByIds方法出现异常,参数:{}", ids, cause);
// 查询购物车允许失败,查询失败,返回空集合
return CollUtils.emptyList();
}
@Override
public void deductStock(List<OrderDetailDTO> items) {
// 库存扣减业务需要触发事务回滚,查询失败,抛出异常
throw new BizIllegalException(cause);
}
};
}
}
②在DefaultFeignConfig类中将
ItemClientFallback注册为一个
Bean
public ItemClientFallback itemClientFallback(){
return new ItemClientFallback();
}
③在Feign的定义接口类中使用
@FeignClient(value="",
configuration=DefaultFeignConfig.class,
fallbackFactory=ItemClientFallback.class)
public interface Client{}
得到的效果反馈是,请求的延迟依旧很高,但是异常比例为0,即不再报错异常
5.2 服务熔断
①使用控制台在对应接口的操作区域选择熔断
②填写相关规则即可