小编目前大一,刚开始着手学习微服务的相关知识,小编会把它们整理成知识点发布出来。我认为同为初学者,我把我对知识点的理解以这种代码加观点的方式分享出来不仅加深了我的理解,或许在某个时候对你也有所帮助,同时也欢迎大家在评论区分享你们的观点。
知不足而奋进,望远山而前行。
目录
概述
前面我们已经学习了远程调用、服务治理、请求路由、身份认证、配置管理 这些与微服务密不可分的知识,但是既然我们拆分了许多服务的模块,那对于某些模块可能发生的问题,我们要做准备一些兜底的方案,又或者是做好健壮性的处理,这就是对于真个微服务的保护。另外之前单体项目时,无论业务多么复杂,操纵多少张表,最终都能够去满足事务的ACID 的特性。但是拆分成很多服务以后,由于服务之间相互独立,各自操作数据库,这就破坏了ACID 的特性,这就属于分布式事务的问题,我们下次再说,这次我们主要讲微服务保护。
雪崩问题
问题概述
微服务调用链路中的某个服务故障,引起整个链路中所有微服务都不可用,这就是雪崩。
由于商品服务的故障,引起其它直接调用或者间接调用商品服务的服务都出现故障,也就导致了整条链路中所有微服务不可用,因此引起了雪崩问题。
具体处理方案如下:
解决方案
**1.请求限流:**限制访问微服务的请求的并发量,避免服务因流量激增而出现故障。
2.线程隔离: 也叫做舱壁模式,模拟船舱隔板的防水原理。通过限定每个业务能使用的线程数量而将故障业务隔离,避免故障扩散。就如下图,服务c的故障,并不会导致服务a故障。
3.服务熔断: 由断路器 统计请求的异常比例或慢调用比例,如果超出阈值则会熔断该业务,则拦截该接口的请求。熔断期间,所有请求快速失败,全都走fallback逻辑。
**4.失败处理:**定义fallback逻辑,让业务失败时不再抛出异常,而是返回默认数据或友好提示。
以上就是解决雪崩问题的常见方案。但是方案总归是方案,具体实现的话,SpringCloud也给我们提供好了对应的组件,有Sentinel和Hystrix等,二者的区别见下图:
而我们接下来将使用Sentinel来实现上述方案,因为它和我们之前使用的Nacos都是阿里巴巴旗下的,使用起来也是中文文档,非常舒舒又服服。
Sentinel
初始Sentinel
Sentinel是阿里巴巴开源的一款微服务流量控制组件。下面这是Sentinel的官网:
Alibaba Sentinel 简介 - spring 中文网 (springdoc.cn)
Sentinel的使用可以分为两部分,分别是核心库和控制台。核心库方面,我们微服务引入对应的jar包,然后去配置流量控制,线程隔离和熔断的规则就好了。规则的配置可以使用Java编码实现,这种方式相对来说比较麻烦,第二种方法就可以使用Sentinel提供的控制台来操作就好了。
官方文档已经给出了jar包,所有我们直需要用Java -jar 运行一下jar包就好了。但是我个人建议配置一下端口属性,防止默认8080端口冲突。
java
java -Dserver.port=8090 -Dcsp.sentinel.dashboard.server=localhost:8090 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
接着我们去浏览器就可以进入Sentinel的控制台界面了,用户名和密码都是sentinel。
这时我们进入之后,因为此时Sentinel还没有与我们的项目建立连接,这时我们只会看到Sentinel监控者自己这个服务的相关接口。
到这里证明我们已经下载并启动好了Sentinel,接着就要让Sentinel整合我们的微服务,这样就相当于建立了二者之间的连接。整合其实很简单,也就是引入相关的依赖,并且配置好Sentinel控制台相关属性。
sentinel依赖如下:
XML
<!--sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
配置的属性只要添加上Sentinel控制台地址就好了。
XML
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8090 # sentinel 控制台地址
这时我们去访问一下购物车接口,再回来看Sentinel控制台,很明显,我们已经实现了当前服务整合Sentinel。
接下来我们来讲一下导航栏的第二个簇点链路。簇点链路指的就是单机调用链路。是一次请求进入服务后经过的每一个被Sentinel监控的监控的资源链。默认Sentinel会监控SpringMVC的每一个Endpoint(http接口)。限流,熔断等都是针对簇点链路中的资源设置的。而资源名默认即使接口的请求路径。
但是又因为我们是基于Restful风格的API请求路径一般都相同,这会导致簇点资源名称重复。因此我们要修改配置,把请求方式+请求路径作为簇点资源名称:
XML
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8090
http-method-specify: true # 是否设置请求方式作为资源名称
接着我们重启服务,进行几次接口访问。这时簇点链路就很丰富了,并且也方便我们进行区分了。
到此为止我们就实现了我们的服务与Sentinel的整合了。
请求限流
这个非常简单,我们只需要在簇点链路后面点击流量控制(流控)按钮,即可对其做限流配置。
弹出下面这个窗口后,我们只需要选择阈值类型是QPS(每秒钟请求数)还是并发线程数,然后设置阈值的数量就好了。我这里就给他设置成6。
设置好后,我们就去jmeter测试一下,还是要用专业的测试工具,不要妄想用你单身二十年的手速去一秒刷新六次以上。
测试结果也是没有问题,通过6,拒绝4。到此请求限流就完成了。
线程隔离
当商品服务出现阻塞或故障时,调用商品服务的购物车服务可能因此而被拖慢,设置资源耗尽。所以必须限制购物车服务中查询商品这个业务的可用线程数,实现线程隔离。
同样我们实现起来也是通过控制台来实现, 实现步骤和上面的流量控制是一样的,我们还是点击流控按钮,但是这一次我们设置阈值类型为并发线程数。这时的阈值表示线程数。
我们在给查询商品做了线程隔离后,我们查询购物车的响应速度是不会发生太大变化的。
以上就是线程隔离的相关知识。
Fallback
在上面线程隔离中,我们商品服务挂载后,线程会一直停在查询购物车,这一块用户的体验是不好的,所以这一块我们要改进一下。我们要给购物车服务加上fallback,当请求不通时,就直接走fallback的逻辑。
首先我们要将FeignClient作为Sentinel的簇点资源,第二步我们要配置FeignClient的Fallback,这里又两种方式,一种时FallbackClass另外一种就是我们之前使用的工厂模式FallbackFactory。这里我们就使用第二种方式。
第一步自定义类,实现FallbackFactory,编写对某个FeignClient的fallback逻辑。第二步将刚刚定义的类注册为一个Bean。第三步在对应的FeignClient接口中使用我们自定义的类。
java
@Slf4j
public class ItemClientFallbackFactory implements FallbackFactory<ItemClient> {
@Override
public ItemClient create(Throwable cause) {
return new ItemClient() {
@Override
public List<ItemDTO> queryItemByIds(Set<Long> ids) {
log.error("查询商品失败!", cause);
return CollUtils.emptyList();
}
@Override
public void deductStock(List<OrderDetailDTO> items) {
log.error("扣减商品库存失败!", cause);
throw new RuntimeException(cause);
}
};
}
}
将上面我们自定义的类注册为一个Bean这一块也是非常简单。接着要想在对应FeignClient接口中使用我们自定义的类,我们只需要在**@FeignClient注解** 后面新增一个fallbackFactory的属性就好了。
java
@FeignClient(value = "item-service", fallbackFactory = ItemClientFallbackFactory.class)
到这里我们就实现了FallBack,在查询失败中不会查询到数据也就是返回空,这样就不会导致服务一直卡在购物车服务这里。
服务熔断
熔断是解决雪崩问题的重要手段。思路是由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该服务。即拦截访问该服务的一切请求。而当服务恢复时,断路器会放行访问该服务的请求。
在熔断器中存在三个状态,分别时Closed,Open,Half-Open。
上面这张图只是流程,我们只需要了解就好了。我们需要做的只是在控制台进行配置就好了。 我们只需要在控制台簇点右侧点击熔断按钮就好了。
RT就表示慢请求的最大时长,比例阈值就表示慢请求所占比例的最大半分比。熔断时长就是当触发熔断,Open状态持续的时长,最小请求数量,就是最少要求多少数量,统计时长就时一个统计时长区间。
以上就是微服务保护的各个方案。但Sentinel的功能不止如此,它的功能十分强大,但一般我们只会用到以上这几个功能。
带着决心起床,带着满意入睡。