基于Sentinel的服务保护方案的三种方式(请求限流、线程隔离、服务熔断)超详细讲解

news/2024/12/28 22:53:37/

目录

1、三种方式介绍

1.1请求限流

1.2 线程隔离方案

1.3 服务熔断

sentinel%E5%AE%9E%E7%8E%B0-toc" style="margin-left:0px;">2、基于sentinel实现

sentinel-toc" style="margin-left:80px;">2.1 启动sentinel

sentinel-toc" style="margin-left:80px;">2.2 基于springboot整合sentinel

2.2.1请求限流

2.2.2请求隔离

2.2.2.1 OpenFeign整合Sentinel

2.2.3 服务熔断

2.2.3.1 编写降级代码

2.2.3.2 服务熔断


1、三种方式介绍

微服务保护的方案有很多,比如:

  • 请求限流

  • 线程隔离

  • 服务熔断

这些方案或多或少都会导致服务的体验上略有下降,比如请求限流,降低了并发上限;

线程隔离,降低了可用资源数量;

服务熔断,降低了服务的完整度,部分服务变的不可用或弱可用。因此这些方案都属于服务降级的方案。但通过这些方案,服务的健壮性得到了提升,

接下来,我们就逐一了解这些方案的原理。

1.1请求限流

服务故障最重要原因,就是并发太高!解决了这个问题,就能避免大部分故障。当然,接口的并发不是一直很高,而是突发的。因此请求限流,就是限制或控制接口访问的并发流量,避免服务因流量激增而出现故障。

请求限流往往会有一个限流器,数量高低起伏的并发请求曲线,经过限流器就变的非常平稳。这就像是水电站的大坝,起到蓄水的作用,可以通过开关控制水流出的大小,让下游水流始终维持在一个平稳的量。

PS:QPS 指的是服务器每秒可以处理的请求数量。

1.2 线程隔离方案

 当一个业务接口响应时间长,而且并发高时,就可能耗尽服务器的线程资源,导致服务内的

其它接口受到影响。所以我们必须把这种影响降低,或者缩减影响的范围。线程隔离正是解决这个

问题的好办法。

  • 业务1:服务A到服务B,限制10线程数
  • 业务2:服务A到服务C,限制10线程数

此时,服务C故障,最大损失10个线程,不会长期占用其他线程,如此,服务A到服务B仍可正常访问,阻止了故障的传递

1.3 服务熔断

线程隔离虽然避免了雪崩问题,但故障服务(商品服务)依然会拖慢购物车服务(服务调用方)的接口响应速度。而且商品查询的故障依然会导致查询购物车功能出现故障,购物车业务也变的不可用了。

所以,我们要做两件事情:

  • 编写服务降级逻辑:就是服务调用失败后的处理逻辑,根据业务场景,可以抛出异常,也可以返回友好提示或默认数据。

  • 异常统计和熔断:统计服务提供方的异常比例,当比例过高表明该接口会影响到其它服务,应该拒绝调用该接口,而是直接走降级逻辑。

sentinel%E5%AE%9E%E7%8E%B0">2、基于sentinel实现

sentinel">2.1 启动sentinel

 Sentinel 是阿里巴巴开源的一款服务保护框架,目前已经加入 SpringCloudAlibaba 中。官

方网站:home | Sentinel

我们可以在这里进行sentinel的一个下载以及查看如何操作和使用,在下载完成后就可以进行我们的操作了

在这里进行jar包下载,Releases · alibaba/Sentinel · GitHub

下载完成后将他放在一个无中文路径的文件夹

在地址栏输入cmd,进入命令操作栏

进来后,输入这段指令,这段指令的作用是用来启动sentinel

java -Dserver.port=8090 -Dcsp.sentinel.dashboard.server=localhost:8090 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

出现这种状况,表示我们的sentinel启动成功了,并且端口号是8090,我们现在可以去浏览器访问他了,并且不要关闭命令操作符

输入localhost:8090,表示我们从本地去访问8090端口号

localhost:8090

出现此页面表示sentinel启动成功了,进入了sentinel的登录页面,这里的账号密码都是sentinel

这里就是我们sentinel真正的首页,进入后就可以开始操作了

sentinel">2.2 基于springboot整合sentinel

首先添加依赖:

<!--sentinel-->
<dependency><groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

在pom.xml文件中添加此依赖

修改application.yaml文件,添加以下代码

spring:cloud: sentinel:transport:dashboard: localhost:8090

重启项目之后,可以在添加了此依赖及代码的地方随机进行一个操作,比如说我在这个商城项目中的购物车cart-service模块中添加了此配置及依赖,那么我就可以对他操作,用来测试

购物车测试

这里我一直刷新购物车这个页面,也就代表着我需要一直访问查看的controller,所以说这样每次访问都被会检测到,再来看看sentinel会是怎么样的

这里可以看到,在这个时间段,不断的有QPS通过,也就是代表着不断有请求被检测到了,虽然看起来很多,但实际上还是很小的,因为我只是手动刷新,达不到那么快的速度,但如果是在双十一这种高并发的情况,那么请求次数就很恐怖了,这里我们就可以做出相应的解决方案

点击《簇点链路》,进入这个页面

        所谓簇点链路,就是单机调用链路,是一次请求进入服务后经过的每一个被 Sentinel 监控的

资源。默认情况下,Sentinel 会监控 SpringMVC 的每一个 Endpoint(接口)。

        因此,我们看到 /carts 这个接口路径就是其中一个簇点,我们可以对其进行限流、熔断、隔

离等保护措施。

        打开 Sentinel 的请求方式前缀,把请求方式 + 请求路径作为簇点资源名:       

添加以下配置:

由于我已经提前添加好了,所以我这里就可以直接看到请求了

http-method-specify: true # 开启请求方式前缀

而我的请求就是这个,可以看到他在一分钟内通过了8次,所以说刚刚我们的请求都发送到他这里

2.2.1请求限流

现在我们就可以对他进行限流了

在弹出的框中这样选择

 这样就把查询购物车列表这个簇点资源的流量限制在了每秒 6 个,也就是最大 QPS 为 6 。c

这里为大家推荐一个软件,可以用来帮助我们测试高并发的

jmeter5.4.1安装步骤-CSDN博客

根据此链接的博主来操作即可

这里发送1000个请求,在100秒内完成,也就是说每秒至少发送10个请求

右击选择启动即可

回到sentinel中进行查看,这里每次通过的都不超过6次,因为我们设置的最大通过数就是6,而不通过数有3有4甚至有5,这是因为虽然每秒10条请求,但也只是平均值,所以说又说会快有时会慢

2.2.2请求隔离

 限流可以降低服务器压力,尽量减少因并发流量引起的服务故障的概率,但并不能完全避免

服务故障。一旦某个服务出现故障,我们必须隔离对这个服务的调用,避免发生雪崩。

        比如,查询购物车的时候需要查询商品,为了避免因商品服务出现故障导致购物车服务级联失败,我们可以把购物车业务中查询商品的部分隔离起来,限制可用的线程资源:

2.2.2.1 OpenFeign整合Sentinel

修改模块的application.yml文件,开启Feign的sentinel功能:

feign:sentinel:enabled: true # 开启feign对sentinel的支持

再修改一下tomcat的配置

server:port: 8082tomcat:threads:max: 50 # 允许的最大线程数accept-count: 50 # 最大排队等待数量max-connections: 100 # 允许的最大连接

然后重启服务,可以看到查询商品的FeignClient自动变成了一个簇点资源:

 这里勾选的是并发线程数限制,也就是说这个查询功能最多使用 5 个线程,而不是 5 QPS。

如果查询商品的接口每秒处理 2 个请求,则 5 个线程的实际 QPS 在 10 左右,而超出的请求自然

会被拒绝。

        接着测试一下:利用 Jemeter 测试,每秒发送 100 个请求:

 进入查询购物车的请求每秒大概在 100,而在查询商品时却只剩下每秒 10 左右,符合我们的

预期。

        当访问其他正常的接口的时候,响应时间非常短,这就证明线程隔离起到了作用,尽管查询购物车这个接口并发很高,但是它能使用的线程资源被限制了,因此不会影响到其它接口。

2.2.3 服务熔断
2.2.3.1 编写降级代码

触发限流或熔断后的请求不一定要直接报错,也可以返回一些默认数据或者友好提示,用户体验会更好。

给FeignClient编写失败后的降级逻辑有两种方式:

  • 方式一:FallbackClass,无法对远程调用的异常做处理

  • 方式二:FallbackFactory,可以对远程调用的异常做处理,我们一般选择这种方式。

这里我们演示方式二的失败降级处理。

(1)在模块中给ItemClientFallbackFactory定义降级处理类,实现 FallbackFactory:

代码如下:

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> {@Overridepublic ItemClient create(Throwable cause) {return new ItemClient() {@Overridepublic List<ItemDTO> queryItemByIds(Collection<Long> ids) {log.error("查询商品信息失败", cause);return CollUtils.emptyList();}@Overridepublic void deductStock(List<OrderDetailDTO> items) {log.error("扣减商品库存失败", cause);throw new RuntimeException(cause);}};}
}

  (2)ItemClientFallbackFactory 注册为 Bean 对象:

@Beanpublic ItemClientFallbackFactory itemClientFallbackFactory(){return new ItemClientFallbackFactory();}

在模块中此接口中添加此属性

重启后,再次测试,发现被限流的请求不再报错,走了降级逻辑:

不会直接报异常错误,而是走 Fallback 逻辑:

当请求被拒绝之后会来到 Fallback 逻辑,我们写的 Fallback 逻辑就是打印日志:

2.2.3.2 服务熔断

        Sentinel 中的断路器不仅可以统计某个接口的慢请求比例,还可以统计异常请求比例。当这

些比例超出阈值时,就会熔断该接口,即拦截访问该接口的一切请求,降级处理;当该接口恢复正

常时,再放行对于该接口的请求。

        断路器的工作状态切换有一个状态机来控制:

状态机包括三个状态:

        1)closed:关闭状态,断路器放行所有请求,并开始统计异常比例、慢请求比例。超过阈值

则切换到 open 状态。

        2)open:打开状态,服务调用被熔断,访问被熔断服务的请求会被拒绝,快速失败,直接

走降级逻辑。Open 状态持续一段时间后会进入 half-open 状态。

        3)half-open:半开状态,放行一次请求,根据执行结果来判断接下来的操作。 

        请求成功:则切换到 closed 状态

        请求失败:则切换到 open 状态


我们可以在控制台通过点击簇点后的熔断按钮来配置熔断策略:

1、点击熔断

这种是按照慢调用比例来做熔断,上述配置的含义是:

        1)RT 超过 200 毫秒的请求调用就是慢调用。

        2)统计最近 1000ms 内的最少 5 次请求,如果慢调用比例不低于 0.5,则触发熔断。

        3)熔断持续时长 20 s 。配置完成后,再次利用 Jemeter 测试,可以发现:

 在一开始一段时间是允许访问的,后来触发熔断后,查询商品服务的接口通过 QPS 直接为

0,所有请求都被熔断了。而查询购物车的本身并没有受到影响。

此时整个购物车查询服务的平均 RT 影响不大:

至此,三种方式都展示完毕


http://www.ppmy.cn/news/1558909.html

相关文章

嵌入式学习-QT-Day06

嵌入式学习-QT-Day06 六、多窗口编程 1、QMessageBox 消息对话框 2、QWidget类 3、parent参数 4、堆栈窗口&#xff08;QStackedWidget&#xff09; 5、新建自定义窗口类 6、对象传值 6.1 父对象 → 子对象 6.2 子对象 → 父对象 7、事件机制 8、QMainWindow主窗口类 8.1 QMenu…

机器学习之scikit-learn(简称 sklearn)

scikit-learn&#xff08;简称 sklearn&#xff09;是 Python 生态中一个非常流行且强大的机器学习库&#xff0c;支持各种机器学习算法和工具。 核心模块和功能 监督学习 (Supervised Learning)&#xff1a; 分类 (Classification): 支持的算法&#xff1a;KNN、SVM、决策树、…

Scala_【2】变量和数据类型

第二章 注释标识符的命名规范命名规则关键字 变量字符串输出数据类型关系变量和数据类型整数类型&#xff08;Byte、Short、Int、Long&#xff09;浮点类型&#xff08;Float、Double&#xff09;字符类型&#xff08;Char&#xff09;布尔类型&#xff08;Boolean&#xff09;…

leetcode hot 100 二叉搜索

35. 搜索插入位置 已解答 简单 相关标签 相关企业 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solut…

Hadoop中MapReduce过程中Shuffle过程实现自定义排序

文章目录 Hadoop中MapReduce过程中Shuffle过程实现自定义排序一、引言二、实现WritableComparable接口1、自定义Key类 三、使用Job.setSortComparatorClass方法2、设置自定义排序器3、自定义排序器类 四、使用示例五、总结 Hadoop中MapReduce过程中Shuffle过程实现自定义排序 一…

CASA模型相关遥感数据及MODIS NDVI、FPAR遥感产品数据时序重建

植被作为陆地生态系统的重要组成部分对于生态环境功能的维持具有关键作用。植被净初级生产力&#xff08;Net Primary Productivity, NPP&#xff09;是指单位面积上绿色植被在单位时间内由光合作用生产的有机质总量扣除自养呼吸的剩余部分。植被NPP是表征陆地生态系统功能及可…

uniapp实现APP、小程序与webview页面间通讯

需求&#xff1a; 1、需要在Uniapp开发的APP或小程序页面嵌入一个H5网页&#xff0c;需要拿到H5给APP传递的数据。 2、并且这个H5是使用vuevant开发的。&#xff08;其实跟使用uniapp开发H5一样&#xff09; 实现步骤&#xff1a; 1、首先需要兼容多端和App端&#xff0c;因…

MATLAB语言的网络编程

标题&#xff1a;MATLAB中的网络编程&#xff1a;深入探索与实践 一、引言 在现代科学和工程领域中&#xff0c;网络编程已经成为了数据处理、信号分析、模型构建等众多任务中不可或缺的一环。MATLAB作为一款强大的数学计算软件&#xff0c;不仅提供了丰富的数值计算功能&…