请求限流

简介: 本文介绍如何使用Sentinel实现接口限流与降级,通过配置QPS阈值保护商品查询接口,并结合JMeter进行压测验证。同时讲解了线程隔离机制,包括信号量隔离的应用,确保系统在高并发下的稳定性。

1.3.1 配置限流策略

下边我们对item-service的商品查询接口进行限流,找到商品查询的簇点链路,点击"流控"

在弹出的菜单中填写QPS单机阈值为5,表示每秒最多处理5个请求

AI:什么是QPS

QPS 是 "Queries Per Second" 的缩写,中文通常称为“每秒查询率”或“每秒请求数”。它是一个衡量系统性能的重要指标,特别是在评估 Web 服务器、数据库系统、API 接口等的负载能力时经常使用。

QPS 表示系统在一秒钟内能够处理的查询或请求的数量。这个指标可以帮助开发者和运维人员了解系统的处理能力和性能瓶颈。例如,如果一个 Web 服务的 QPS 为 100,则意味着该服务在一秒钟内最多可以处理 100 个请求。

你的主打项目必须要提前准备好:QPS、TPS、RT、下载量、日活、最大数据量的表是什么

1.3.2 限流测试

首先去掉item-service服务中查询商品信息接口的休眠代码。然后启动item服务

下边我们用jmeter压力测试工具进行压力测试:Jmeter快速入门

JMeter 是一个广泛使用的开源性能测试工具,主要用于测试 Web 应用程序的负载和性能。它是由 Apache Software Foundation 开发和维护的,完全用 Java 编写,因此可以在任何支持 Java 的平台上运行。

找到课程资料中的JMeter安装包apache-jmeter-5.4.1.zip,解压到非中文的目录,进入bin下双击打开jmeter.bat

打开软件切换到中文

接下来找到课程资料下的“雪崩测试.jmx” 拖到JMeter面板中

最终效果如下(如有不同,及时修改)

设置模拟线程数等参数:

表示:总共发送1000个请求,用100秒发送,循环次数是1即执行10秒结束。

根据设置参数可知,每秒发送10个秒在100秒可完成1000个请求。

在“HTTP请求”界面设置压力测试请求的地址:确保跟你本地端口一致

右键“限流测试”点击“启动”

测试结果可以在“汇总报告”中查看,每次请求的次数在“察看结果树”中查看。

从吞吐量可以看出每秒发送10个请求,异常数是0

通过sentinel的实时监控界面可以看出对商品查询接口的请求,通过的QPS为5,拒绝QPS为5。

因为上边我们配置了对商品查询接口限流QPS为5,所以每秒10个请求查询/carts,远程调用商品查询服务接口的QPS只有5,说明被限流了。

注意:如果实时监控图无法正常显示需要进入虚拟机进行时间同步。

ntpdate ntp1.aliyun.com
如果无法执行上边的命令需要下载ntpdate
yum install ntpdate -y

此时,需要耐心等待一下后重试,就可以看到有结果了:通过只有5。

如果你还是没有,也可以调整Jmeter参数,把1000,100改成:100,10,循环次数:永远

再查看每次的请求和响应数据发现,由于编写了商品查询接口远程调用的降级逻辑,当商品查询接口被限流后将会走降级方法,从jmeter测试结果可以看到被限流的请求无法获取商品信息

再查看cart-service的控制台,在降级方法中捕获到了 com.alibaba.csp.sentinel.slots.block.flow.FlowException 异常,这说明接口被限流后sentinel客户端会抛出FlowException 异常。

查看Jmeter也可以看到大量拒绝信息

1.3.3 小节

sentinel限流怎么实现?

我们项目使用Sentinel实现限流控制。

  1. 首先在服务提供方配置sentinel,引入sentinel的依赖,配置sentinel的地址
  2. 通过Sentinel控制台配置限流策略,可以配置QPS阈值、并发线程数等。
  3. 当方法被限流会走直接拒绝。

1.4. sentinel降级

上面讲的是A--Feign/Dubbo->B服务时候,对B的做熔断、限流,可如果我只想对A本身做限流怎么实现?

1.4.1 问题描述

下边我们对/carts接口进行限流测试,找到GET/carts簇点

点击“流控” 设置QPS 单机阈值为6

截止目前,我们一共设置了两个流控规则

用jmeter测试,通过sentinel进行实时监控,通过QPS为6,拒绝QPS为4,符合我们的预期结果

当/carts接口被限流时我们访问此接口(需要在Jmeter压测期间测试),需要连续多点击几次

结果内容:Blocked by Sentinel (flow limiting),从字面内容看是被sentinel限流。

为什么访问item-service的商品查询接口走了降级方法,而访问/carts没有走降级方法呢?

1.4.2 sentinel实现降级

这里我们需要重新梳理下:

前边cart-service远程调用item-service服务的商品查询接口正常走降级方法,这是因为我们编写了ItemClient接口的降级类ItemClientFallbackFactory,并且我们在cart-service服务中集成了sentinel,在cart-service的application.yml配置文件中配置了feign使用sentinel,如下:

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

也就说,在cart-service通过openfeign远程调用item-service时通过sentinel进行降级,最终执行ItemClientFallbackFactory类中指定的降级方法。这里我们是对/carts进行限流,并没有针对此接口编写降级方法

AI:sentinel实现降级

针对feign远程调用我们通过实现FallbackFactory接口去编写远程调用接口对应的降级逻辑,而针对非feign远程调用的降级逻辑我们需要使用@SentinelResource注解去实现

首先使用 @SentinelResource  定义资源,编写降级方法

@ApiOperation("查询购物车列表")
@SentinelResource(value = "queryMyCarts", fallback = "queryMyCartsFallback", blockHandler = "queryMyCartsBlockHandler")
@GetMapping
public List<CartVO> queryMyCarts(){
    return cartService.queryMyCarts();
}
//当发生非限流非熔断异常走此方法
public List<CartVO>  queryMyCartsFallback(Throwable throwable){
log.error("非限流、非熔断异常执行的降级方法,throwable:",  throwable);
return new ArrayList<>();
}
//当发生熔断、限流走此方法
public List<CartVO>  queryMyCartsBlockHandler( BlockException blockException){
log.error("触发限流、熔断时执行的降级方法,blockException:",  blockException);
return new ArrayList<>();
}

然后在sentinel中设置资源的流控

删除针对/carts设置的流控规则

再次使用jmeter进行压力测试

观察cart-service控制台,当/carts限流后正常执行降级方法,日志如下:

18:37:31:767 ERROR 4696 --- [nio-8082-exec-9] c.hmall.cart.controller.CartController   : 触发限流、熔断时执行的降级方法,blockException:

在降级方法中可以返回特殊的信息,或指定特殊的状态码,根据特殊值前端可展示为类似“网络忙请稍后重试” 这样的信息。此时限流期间访问购物车接口,发现就走了降级逻辑,返回空集合:

1.4.3 小节

sentienl降级怎么实现?

对于Feign远程调用对每个远程调用接口实现降级方法,通过实现FallbackFactory接口实现降级方法。

对于非Feign远程调用我们使用@SentinelResource注解编写自定义降级方法。

1.5. 线程隔离

1.5.1 方案介绍

首先我们来看下线程隔离功能,无论是Hystix还是Sentinel都支持线程隔离。不过其实现方式不同。

线程隔离有两种方式实现:

  • 线程池隔离:给每个服务调用业务分配一个线程池,利用线程池本身实现隔离效果
  • 信号量隔离:不创建线程池,而是计数器模式,记录业务使用的线程数量,达到信号量上限时,禁止新的请求

如图:

Sentinel的线程隔离就是基于信号量隔离实现的,而Hystix两种都支持,但默认是基于线程池隔离。

1.5.2 Sentinel线程隔离(练习)

下边我们使用Sentinel实现基于信号量的线程隔离。

点击查询商品的FeignClient对应的簇点资源后面的流控按钮:

在弹出的表单中填写下面内容:

注意,这里勾选的是并发线程数限制,也就是说这个查询功能最多使用5个线程,而不是5QPS。如果查询商品的接口每秒处理2个请求,则5个线程的实际QPS在10左右,而超出的请求自然会被拒绝。

cart-service调用商品查询控制在5个线程内,通过线程隔离即使商品服务出现问题也不会影响cart-service服务。

下边修改商品查询接口的代码,添加休眠500毫秒的代码,模拟一次请求需要500毫秒,一秒则可处理2次请求,5个线程可接收10 QPS左右。

将/carts的限流规则调大以免影响商品查询接口的限流控制。

下边使用jmeter进行测试,更改线程数为10000,时间为100秒,每秒需要发送100个请求。

启用测试,通过sentinel实时监控,符合我们的预期。

不知道细心的你是否发现了一个事情:我们设置的Sentinel通过数量,为什么不那么精准呢?

  • 窗口边界:一个请求可能刚好跨越两个窗口,导致单个窗口的统计值略高于设定值。
  • 滑动窗口精度:滑动窗口的划分粒度可能无法完全精确,尤其在请求密集时。
相关文章
|
1天前
|
uml C语言
系统时序图
时序图是UML中描述对象间消息传递时间顺序的交互图,横轴为对象,纵轴为时间。用于展示交互流程、强调时序关系,直观表达并发过程。主要元素包括角色、对象、生命线、控制焦点和消息等,广泛应用于系统设计与分析。
系统时序图
|
2天前
|
消息中间件 存储 数据挖掘
应用架构图
技术架构是将业务需求转化为技术实现的关键过程,涵盖分层设计、技术选型与系统集成。本文详解单体与分布式架构,包括展现层、业务层、数据层及基础层的构建逻辑,并通过调用关系图明确系统边界与外部依赖,支撑高效稳定的技术体系落地。
应用架构图
|
1天前
|
消息中间件 Java 数据安全/隐私保护
RabbitMQ入门
RabbitMQ是基于Erlang开发的开源消息中间件,支持AMQP协议,实现应用间解耦与异步通信。其核心组件包括生产者、消费者、队列、交换机和虚拟主机,可通过Docker快速部署并结合SpringAMQP实现消息收发。
Topic交换机(自行测试)
Topic交换机支持通配符匹配RoutingKey,实现灵活路由。BindingKey用`.`分隔,`*`匹配一个词,`#`匹配零个或多个词。相比Direct交换机,Topic更适用于复杂路由场景。
Direct交换机
Direct交换机根据RoutingKey将消息路由到指定队列,实现精准消息分发。与Fanout广播模式不同,Direct支持多队列绑定相同Key,兼具灵活性与定向投递优势。
Direct交换机
|
1天前
|
项目管理 开发者
业务架构图
本文系统阐述了业务架构图的核心概念与绘制方法,涵盖业务定义、架构分层(组织层、应用层、能力层、基础层)、模块划分及功能分解,并结合医院场景示例,说明如何通过分层、分模块、分功能构建清晰的业务视图,提升客户理解与开发效率。
|
1天前
|
存储 Dubbo API
SpringCloud工程部署启动
本文介绍SpringCloud微服务工程搭建全过程,涵盖项目创建、数据库配置、服务部署及远程调用实现。通过两种方案导入工程,完成user-service与order-service模块开发,并利用RestTemplate实现跨服务数据调用,帮助理解微服务间通信机制及拆分逻辑。
|
1天前
|
SQL 关系型数据库 数据库
分布式事务
本文介绍了分布式事务的概念、典型场景及解决方案。在微服务架构下,一次业务操作需跨多个数据库和远程调用协作完成,传统本地事务无法保证整体一致性。通过Seata框架可实现分布式事务控制,其AT模式无侵入、高性能,基于两阶段提交与undo log实现最终一致;XA模式则提供强一致性但性能较低。文章还结合下单、支付等场景演示了Seata的集成与应用。
|
1天前
|
监控 Java Sentinel
熔断降级
熔断降级是防止服务雪崩的核心机制,通过Sentinel实现。熔断由客户端断路器统计异常或慢请求比例,超阈值后拦截请求;降级则返回默认数据保障体验。结合使用可快速失败、避免级联故障。
|
1天前
|
人工智能 Java 应用服务中间件
微服务保护
本节介绍微服务雪崩问题及保护方案。当某服务故障或负载过高,可能引发级联失败,导致整个系统不可用。为避免此问题,需采取熔断、降级、超时、线程隔离和限流等措施。常用工具包括Hystrix、Resilience4j和Sentinel,课程重点讲解Sentinel的使用。