目录
[1.1 雪崩问题(级联失败问题)示意图](#1.1 雪崩问题(级联失败问题)示意图)
[1.2 雪崩问题的产生原因与解决策略](#1.2 雪崩问题的产生原因与解决策略)
[2.1 请求限流](#2.1 请求限流)
[2.2 线程隔离](#2.2 线程隔离)
[2.3 服务熔断](#2.3 服务熔断)
[2.4 总结------具体解决策略](#2.4 总结——具体解决策略)
[3.1 sentinel 介绍](#3.1 sentinel 介绍)
[3.2 sentinel安装](#3.2 sentinel安装)
[3.3 sentinel微服务整合](#3.3 sentinel微服务整合)
[3.4 簇点链路调整](#3.4 簇点链路调整)
[4.1 配置请求限流说明](#4.1 配置请求限流说明)
[4.2 请求限流实践](#4.2 请求限流实践)
[4.2.1 配置请求限流规则](#4.2.1 配置请求限流规则)
[4.2.2 JMeter并发测试](#4.2.2 JMeter并发测试)
[4.2.3 sentinel流控展示](#4.2.3 sentinel流控展示)
[5.1 模拟无线程隔离配置阻塞请求压垮服务器实验](#5.1 模拟无线程隔离配置阻塞请求压垮服务器实验)
[5.1.1 配置慢请求业务](#5.1.1 配置慢请求业务)
[5.1.2 调整服务器资源量](#5.1.2 调整服务器资源量)
[5.1.3 正常请求现象展示](#5.1.3 正常请求现象展示)
[5.1.4 JMeter压力测试并查看接口响应情况](#5.1.4 JMeter压力测试并查看接口响应情况)
[5.2 配置线程隔离规则](#5.2 配置线程隔离规则)
[5.3 JMeter并发测试](#5.3 JMeter并发测试)
[5.4 sentinel流控效果显示](#5.4 sentinel流控效果显示)
[6.1 fallback实验说明](#6.1 fallback实验说明)
[6.2 调整簇点策略,注册OpenFeign簇点](#6.2 调整簇点策略,注册OpenFeign簇点)
[6.3 FallbackFactory配置Fallback](#6.3 FallbackFactory配置Fallback)
[6.3.1 编写ItemClientFallbackFactory类](#6.3.1 编写ItemClientFallbackFactory类)
[6.3.2 在Config中注册Bean对象](#6.3.2 在Config中注册Bean对象)
[6.3.3 在对应的Client上添加注解使用](#6.3.3 在对应的Client上添加注解使用)
[6.4 线程隔离 + Fallback实验测试](#6.4 线程隔离 + Fallback实验测试)
[6.4.1 给feign簇点添加线程隔离规则](#6.4.1 给feign簇点添加线程隔离规则)
[6.4.2 JMeter并发测试并查看响应结果](#6.4.2 JMeter并发测试并查看响应结果)
[6.4.3 sentinel流控效果展示](#6.4.3 sentinel流控效果展示)
[7.1 断路器介绍](#7.1 断路器介绍)
[7.2 配置服务熔断规则说明](#7.2 配置服务熔断规则说明)
[7.3 JMeter并发测试并进行前后对比](#7.3 JMeter并发测试并进行前后对比)
实验环境说明
本文有部分地方需要实验进行。首先对于看过黑马微服务的同学应该会比较熟悉。如果没有你也可以参考我实验的环境搭个简单的测试环境,用于实验。实验的目的也是为了更好的理解业务、理解知识点。
本地环境部分:
|---------------|---------------|-----------|
| 服务名 | 端口号 | 备注 |
| nginx | 18080 / 18081 | 前端运行环境 |
| sentinel | 8090 | 服务保护监控 |
| hm-gateway | 8080 | 后端项目网关模块 |
| item-service | 8081 | 后端商品服务模块 |
| cart-service | 8082 | 后端购物车服务模块 |
| item-service2 | 8083 | 后端商品服务模块 |
| item-service3 | 8084 | 后端商品服务模块 |
| user-service | 8085 | 后端用户管理模块 |
| trade-service | 8086 | 后端交易服务模块 |
| pay-service | 8087 | 后端支付服务模块 |
远程服务器环境部分:
|-----------|-------------|-----------------|
| 服务名 | 端口号 | 备注 |
| nacos | 8848 | 注册中心及配置中心,非容器镜像 |
| nginx | 18080/18081 | 线上前端运行环境,容器镜像 |
| mysql | 3306 | 线上数据库,容器镜像 |
| docker-hm | 8080 | 线上后端运行环境,容器镜像 |
注意事项:
- 远程环境中非容器镜像指nacos是后单独配置的容器,而mysql、nginx、docker-hm是使用compose统一部署的。
- 在本节实验中,线上环境的nginx和docker-hm我们不会使用到,而是使用本地的nginx和后端项目
- 请你确保在配置线上环境时,mysql必须先比nacos启动。如果nacos先启动将无法连接数据库。此时你需要停止nacos容器,先启动mysql。
前言
先前我们依次学习了远程调用、服务治理、请求路由、身份认证、配置管理的相关知识。本篇,我们将从雪崩问题出发,去探讨微服务的保护措施及实现方法。
一、一片小雪花引起的雪崩!
1.1 雪崩问题(级联失败问题)示意图
微服务调用链路中的某个服务故障,引起整个链路中的所有微服务都不可用,这就是雪崩。
1.2 雪崩问题的产生原因与解决策略
|-------------------------------------|---------------------------------------------|
| 产生原因 | 解决策略 |
| 服务相互调用,而服务提供者出现故障或阻塞 | 尽量避免服务提供者出现阻塞,限制请求数量【请求限流】 |
| 服务调用者被大量阻塞请求占满,导致服务器崩溃 | 尽量避免无节制的调用服务器资源请求异常服务,限制调用服务的线程数量【线程隔离】 |
| 调用链中连环失败,没有及时阻断,对于异常请求仍然不断去重试,浪费资源。 | 尽量避免对已经确认异常的服务继续发送请求,及时做到断止请求【服务熔断】 |
总结:确保服务提供者能处理它能力范围内的请求,同时服务调用者要设置好合适的线程数,以免请求占满服务器资源。最后,如果服务提供者出现大量异常后,也要及时断舍,不要再做无意义的请求去浪费资源。
二、雪崩问题的具体解决策略
2.1 请求限流
**请求限流:**限制访问微服务的请求的并发量,避免服务因流量激增出现故障。
2.2 线程隔离
**举例:**就像将船分为若干块,即使一块进水了,也不会导致整船的进水。减少对整体的影响。
线程隔离:相当于利用线程将服务器隔离成多块,即使部分异常也不会拖垮服务器,减少对服务器的影响。
**fallback优化:**有时候我们不希望抛出服务异常,这时我们可以让异常的服务调用变成自定义的fallback逻辑,这样一来可以快速失败,执行fallback中的业务逻辑,返回默认数据或友好提示。
2.3 服务熔断
**举例:**就像家庭电路中的空气开关。当电器出现漏电异常或者短路时,空气开关会自动切断电源,以免照常更多的电器损失。
**服务熔断:**由断路器统计请求的异常比例或慢调用比例,如果超出阈值则会熔断该业务,则拦截该接口的请求。 熔断期间,所有请求快速失败,全都走fallback逻辑。
fallback逻辑:对于需要熔断的服务,没有必要再发送请求浪费,直接熔断并且走fallback,执行服务异常时的业务逻辑。
2.4 总结------具体解决策略
|----------|-----------------------------------------|
| 请求限流 | 限制流量在服务可以处理的范围,避免因突发流量而故障 |
| 线程隔离 | 控制业务可用的线程数量,将故障隔离在一定范围 |
| 服务熔断 | 将异常比例过高的接口断开,拒绝所有请求,直接走fallback |
| 失败处理 | 定义fallback逻辑,让业务失败时不再抛出异常,而是返回默认数据或友好提示 |
三、微服务保护工具:sentinel
3.1 sentinel 介绍
Sentinel是阿里巴巴开源的一款微服务流量控制组件。Sentinel定位是分布式系统的流量防卫兵。目前互联网应用基本上都使用微服务,微服务的稳定性是一个很重要的问题,而限流、熔断降级 是微服务保持稳定的一个重要的手段。
home | Sentinelhomehttps://sentinelguard.io/zh-cn/index.html
Sentinel主要的功能示意图
3.2 sentinel安装
【下载】
sentinel的下载地址 Releases · alibaba/Sentinelhttps://github.com/alibaba/Sentinel/releases 下载后放到非中文目录下,将版本后缀删除:
【运行】
打开cmd命令窗口,运行启动脚本
java
java -Dserver.port=8090 -Dcsp.sentinel.dashboard.server=localhost:8090 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
【访问】
本地访问 localhost:8090端口,即可进入控制台。(登录账号密码默认都是sentinel)
3.3 sentinel微服务整合
【基本步骤】
- 引入sentinel依赖
- 配置控制台发现
- 访问微服务,测试sentinel监控
以下实验以cart-service模块为例:
【引入依赖】
XML
<!--sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
【增加配置文件】
bash
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8090
【重启测试服务】
对购物车的相关服务进行访问,查看sentinel的监控效果
3.4 簇点链路调整
**簇点链路:**就是单机调用链路。是一次请求进入服务后经过的每一个被Sentinel监控的资源链。默认Sentinel会监控SpringMVC的每一个Endpoint(http接口)。限流、熔断等都是针对簇点链路中的资源设置的。而资源名默认就是接口的请求路径:
当前项目基于restful风格,还存在一些不合适的问题:
如何让每个接口都能显示出来呢?我们需要对簇点链路配置进行一些调整:
修改配置文件,添加一行配置:
bash
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8090
http-method-specify: true # 开启请求方式前缀
重新上线测试:
四、基于sentinel实现请求限流
4.1 配置请求限流说明
在簇点链路后面点击流控按钮,即可对其做限流配置:
4.2 请求限流实践
以下实验以获取购物车列表接口为例:
4.2.1 配置请求限流规则
4.2.2 JMeter并发测试
4.2.3 sentinel流控展示
五、基于sentinel实现线程隔离
5.1 模拟无线程隔离配置阻塞请求压垮服务器实验
本实验以购物车列表查询接口为例:由于购物车列表需要依赖商品查询的数据,因此可以进行本次实验。(完成本次实验前,请将请求限流规则删除)
5.1.1 配置慢请求业务
将根据ID批量查询商品接口改为慢查询
5.1.2 调整服务器资源量
为了能更快展现压垮服务器的情况,我们需要把tomcat服务器默认的资源量**(默认8192)**改小一点。
5.1.3 正常请求现象展示
购物车列表查询速度500多毫秒,且目前正常查询到商品数据
其他购物车接口查询速度正常,10多毫秒
5.1.4 JMeter压力测试并查看接口响应情况
这一步需要在JMeter高并发请求的过程中进行。
【利用JMeter不断发送购物车列表请求,压力服务器】
【查看购物车接口的响应结果】
【更加暴力的测试 】提高到每秒400并发
(哥们别测太高,电脑死机就完蛋了)
5.2 配置线程隔离规则
5.3 JMeter并发测试
5.4 sentinel流控效果显示
六、fallback逻辑优化
6.1 fallback实验说明
第五节线程隔离中存在一个问题:发现没有,控制台基本上全是报错的,但是有时后我们不希望服务抛出异常,而是在服务异常后走我们自定义的业务逻辑。这个时候就需要fallback登场了。
以查询购物车列表为例,在商品查询业务慢导致线程占满,返回请求429的情况下。我们希望还能正常显示购物车列表信息。对此,我们可以给查询逻辑添加fallback,在资源耗尽被拒绝的时候,我们直接走fallback,将单单购物车的数据展示到前端就行了(不管商品信息)
也就是说,我们不需要隔离购物车业务,而是直接隔离异常的商品查询接口!
但是,调用商品查询接口是OpenFeign调用,如何给这条链路添加上线程隔离规则呢?
我们必须先将这条链路注册成一个簇点。接下来就跟着我一起实验吧!
6.2 调整簇点策略,注册OpenFeign簇点
在cart-service模块中,开启feign对sentinel的支持
bash
feign:
sentinel:
enabled: true # 开启feign对sentinel的支持
重启查看sentinel
接下来我们就可以对这个接口进行流控啦!不过在此之前我们先配置一下fallback逻辑,
给FeignClient编写失败后的降级逻辑有两种方式:
-
方式一:FallbackClass,无法对远程调用的异常做处理
-
方式二:FallbackFactory,可以对远程调用的异常做处理,我们一般选择这种方式。
6.3 FallbackFactory配置Fallback
6.3.1 编写ItemClientFallbackFactory类
在hm-api模块下新建client.fallback.itemClientFallbackFactory.java,并实现FallbackFactory接口
java
package com.hmall.api.client.fallback;
import com.hmall.api.client.ItemClient;
import com.hmall.api.dto.ItemDTO;
import com.hmall.api.dto.OrderDetailDTO;
import com.hmall.common.utils.CollUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import java.util.Collection;
import java.util.List;
@Slf4j
public class ItemClientFallbackFactory implements FallbackFactory<ItemClient> {
@Override
public ItemClient create(Throwable cause) {
return new ItemClient() {
@Override
public List<ItemDTO> queryItemByIds(Collection<Long> ids) {
log.error("查询商品信息失败: ", cause);
// 返回空集合
return CollUtils.emptyList();
}
@Override
public void deductStock(List<OrderDetailDTO> items) {
log.error("扣减库存失败: ", cause);
throw new RuntimeException(cause);
}
};
}
}
6.3.2 在Config中注册Bean对象
java
@Bean
public ItemClientFallbackFactory itemClientFallbackFactory() {
return new ItemClientFallbackFactory();
}
6.3.3 在对应的Client上添加注解使用
到此为止,Fallback已经编写完成了,接下来再次进行线程隔离实验测试
6.4 线程隔离 + Fallback实验测试
6.4.1 给feign簇点添加线程隔离规则
6.4.2 JMeter并发测试并查看响应结果
查询购物车列表不报错了,而且查询从500多毫秒变成了几十毫秒
6.4.3 sentinel流控效果展示
七、基于sentinel实现服务熔断
7.1 断路器介绍
熔断是解决雪崩问题的重要手段。思路是由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该服务。即拦截访问该服务的一切请求;而当服务恢复时,断路器会放行访问该服务的请求。
知道服务已经挂了,就不需要再给他发请求了,直接拒绝发起请求,直接走fallback逻辑。进而节约更多的资源。与此同时,服务熔断需要有一个恢复时长,在恢复时再次请求查看是否成功。成功就结束熔断,否则继续进入熔断状态!
7.2 配置服务熔断规则说明
7.3 JMeter并发测试并进行前后对比
不加服务熔断前的状态:
加了服务熔断后的状态
超过熔断时间20s后,请求恢复正常
八、微服务保护方案相关知识追问巩固
-
请你谈谈微服务雪崩问题是如何产生的?产生的后果是什么?
-
对于雪崩问题,你有哪些好的解决方案呢?
-
你知道什么是流量控制组件么?你有用过哪些微服务流量控制组件?
-
请你谈谈sentinel如何整合到我们的微服务项目中?说出具体的步骤?
-
关于sentinel簇点的概念?什么是簇点链路?
-
restful风格的微服务项目使用sentinel簇点需要注意什么问题?如何配置?
-
openfeign调用如何注册到sentinel的簇点链路中?
-
openfeign调用的请求如何单独给它加上流量控制规则?具体的步骤是什么?
-
请你谈谈使用sentinel如何实现请求限流、线程隔离?
-
请你谈谈如何编写fallback逻辑,具体的步骤是什么?
-
请你谈谈使用sentinel如何实现服务熔断,熔断有哪些常见的策略?
-
请你谈谈服务熔断中熔断器的工作流程,什么是熔断时长?