当前位置: 首页 > article >正文

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

目录

1、三种方式介绍

1.1请求限流

1.2 线程隔离方案

1.3 服务熔断

2、基于sentinel实现

2.1 启动sentinel

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 服务熔断

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

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

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

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

2、基于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真正的首页,进入后就可以开始操作了

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: 8082
  tomcat:
    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> {
    @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);
            }
        };
    }
}

  (2)ItemClientFallbackFactory 注册为 Bean 对象:

@Bean
    public 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.kler.cn/a/455580.html

相关文章:

  • vue3使用element-plus,解决 el-table 多选框,选中后翻页再回来选中失效问题
  • SQL 实战:动态表创建与多表更新的高级 SQL
  • Linux总结之CentOS Stream 9安装mysql8.0实操安装成功记录
  • JavaWeb(一) | 基本概念(web服务器、Tomcat、HTTP、Maven)、Servlet 简介
  • SQL 实战:日期与时间函数 – 统计数据的时间跨度与趋势
  • 永磁同步电动机直接转矩控制的研究
  • AR 模型的功率谱
  • 优雅草央千澈-关于蓝湖如何快速的标注交互原型是如何使用的-如何使用蓝湖设计交互原型和整个软件项目的流程逻辑-实践项目详细说明
  • 卷积神经网络-三维卷积
  • 请分别从CPU、内 存、IO、⽹络的⻆度判断Linux的瓶颈?
  • 【数据库学习笔记】SQL触发器(例题+代码)
  • STM32F103RCT6学习之二:GPIO开发
  • Java 中的 7 种重试机制
  • 网狐旗舰版源码搭建概览
  • uniapp小程序使用webview 嵌套 vue 项目
  • Cursor 0.43版本更新:Agent功能让开发更高效
  • linux 查看服务是否开机自启动
  • 手机发烫怎么解决?
  • 【前端】入门指南:Vue中使用Node.js进行数据库CRUD操作的详细步骤
  • 王者荣耀游戏中帧同步如何分离逻辑和渲染
  • 【ES6复习笔记】函数参数的默认值(6)
  • 深度学习助力股市预测:LSTM、RNN和CNN模型实战解析
  • ZLG嵌入式笔记 | 电源设计避坑(上)
  • LeetCode-最长回文子串(005)
  • 视频编码中的算法、技术学习
  • B树B+树