Spring Cloud中怎么使用Resilience4j RateLimiter对接口进行限流

news2024/9/20 15:02:30

在微服务架构中,限流是保护系统稳定性的重要手段之一。限流可以防止某个服务因流量过大而过载,影响整个系统的稳定性和性能。Resilience4j 提供了多种限流策略,其中 RateLimiter 是一种常用的限流机制。本文将详细介绍如何在 Spring Cloud 项目中使用 Resilience4j RateLimiter 对接口进行限流。

 1.Resilience4j 简介

Resilience4j 是一个轻量级的容错库,支持函数式编程设计。它提供了多种容错机制,包括熔断器(Circuit Breaker)、限流器(Rate Limiter)、重试(Retry)、舱壁(Bulkhead)等。相比于 Hystrix,Resilience4j 更加轻量级,并且在上篇文章中提到随着Hystrix停止维护,Resilence4j成了spring cloud官方主推的容错库。上篇文章我们介绍了熔断器,今天我们继续介绍它提供的限流器组件RateLimiter。

2. 原理解析

Resilience4j 的 RateLimiter 实现了基于时间窗口的限流策略。它主要采用令牌桶(Token Bucket)算法来控制请求速率。

令牌桶算法是一种常见的限流算法。它通过在固定的时间间隔生成令牌并将其存储在桶中,当请求到达时,从桶中获取令牌,如果桶中有足够的令牌,则请求通过,否则请求被限流。

下面是官网中关于RateLimiter的工作流程介绍,我们通过这张图来详细的了解一下,它的工作原理。

  •  纳秒时间轴:图中的横轴为系统时间单位是纳秒,表示从JVM启动到当前时间段。
  • cycle:上图中的cycle表示一个时间窗口周期。在每个时间窗口结束后,RateLimiter会刷新令牌桶。
  • permissions:图中的 permissions 表示当前时间窗口周期内可用的令牌数。在每个时间窗口周期开始时,令牌数被重置为配置的最大值(例如每秒 10 个令牌)。
  • 令牌生成:系统以固定速率生成令牌,并将令牌放入桶中。例如,每秒生成 10 个令牌。在每个时间窗口周期开始时,令牌数被重置为最大值。
  • 令牌获取:当一个请求到达时,需要从桶中获取一个令牌。如果桶中有足够的令牌,则请求通过(acquire),并从桶中扣减一个令牌。如果桶中没有令牌,则请求被限流或等待。
  • 令牌刷新:在每个时间窗口周期结束时,RateLimiter 会刷新令牌桶,重置可用的令牌数。

上面图中的两个线程Thread1发起请求,并成功获取令牌(acquire),然后持续运行。Thread2尝试获取令牌(reserve),但是令牌桶中没有足够的令牌,导致线程进入等待状态(park)。当新的时间窗口开始,刷新令牌桶后,Thread2成功获取到令牌并继续运行。

3. Spring Cloud项目中集成

3.1 在pom文件中添加相关的依赖
<!--resilience4j-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<!-- 由于resilience4j需要AOP的包,所以必须导入AOP包 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
3.2 在application.yml中添加RateLimiter相关的配置
####resilience4j ratelimiter 限流的例子
# 以下配置将RateLimiter设置为每60秒允许5次请求,并且当请求超过限流时,不会有任何等待时间,直接返回失败。
resilience4j.ratelimiter:
  configs:
    default:
      registerHealthIndicator: false #是否注册为健康检查
      limitForPeriod: 5 #在一次刷新周期内,允许执行的最大请求数为5
      limitRefreshPeriod: 60s # 限流器每隔limitRefreshPeriod也就是60s刷新一次,将允许处理的最大请求数量重置为limitForPeriod本案例中为5
      timeoutDuration: 0 # 线程等待权限的默认等待时间,0就是不等待
      eventConsumerBufferSize: 100 # 配置了事件缓冲区的大小为100,用于记录和监控RateLimiter的行为
3.3 在需要限流的接口中通过注解开启限流

需要限流的接口通常是服务的下游,我们写一个简单的例子。

@RestController
public class PayController {

    private static final Logger log = LoggerFactory.getLogger(PayController.class);

    @GetMapping("/pay/{id}")
    @RateLimiter(name = "pay-service",fallbackMethod = "payServiceFallback")
    public String pay(@PathVariable("id") Integer id){
        log.info("Pay For Order id: {}", id);
        if (id == 1) { // 模拟服务异常
            throw new RuntimeException("Pay Service Exception");
        }
        return "Pay Success";
    }
    // 限流后的降级处理方法
    public String payServiceFallback(Integer id,Throwable t)
    {
        log.info("Pay Service invoke failed for order ID: {}", id);
        log.error("Error: {}", t.getMessage());
        return "Pay service is currently overloaded. Please try again later!";
    }
}

上游我们再模拟一个服务,通过OpenFeign调用。

@RestController
public class OrderController {

    private static final Logger log = LoggerFactory.getLogger(OrderController.class);

    @Autowired
    private PayService payService;
    @GetMapping("/order/{id}")
    @CircuitBreaker(name = "paymentService", fallbackMethod = "fallback")//配置熔断器
    public String order(@PathVariable("id") Integer id){
        log.info("Order id: {}", id);
        log.info("Request Pay For Order id: {}", id);
        //通过open feign远程调用支付服务
        return payService.payOrder(id);
    }

    //fallback就是服务降级后的兜底处理方法
    public String fallback(Integer id,Throwable t) {
        log.info("Pay Service invoke failed for order ID: {}", id);
        log.error("Error: {}", t.getMessage());
        return "Pay Service Was Busy Now. Please try again later!";
    }
}

4. 运行和测试

将这两个服务启动起来,进行测试。

在60s内访问支付接口5次后开始限流

在浏览器中访问:http://localhost:8082/order/5

从日志中可以看出,在连续访问这个接口5次后,限流功能开启,这个接口不允许继续访问,并走到了降级的方法。等到下一个时间窗口时,会自动刷新令牌数量。

5. 总结

通过本文的示例,我们学习了如何在 Spring Cloud 项目中使用 Resilience4j RateLimiter 对接口进行限流。Resilience4j 的 RateLimiter 提供了一种简单而有效的方式来保护服务免受过载影响提高系统的稳定性和可靠性。结合 Feign Client 和熔断器,可以构建出高可用的微服务架构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1937402.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

组内第一次会议

会议内容 1、科研平台使用 增删改查对文件 cp -r /root/mmdetection/dataset/ /root/user/wbzExperiment/mmdetection/ rm -r /root/user/yolov5-master tar -czvf test03.tar.gz test03/ unzip abc.zip 上传文件、解压文件&#xff1a;要在自己的目录中&#xff0c;进入…

普中51单片机:LED点阵屏组成结构及实现方法详解(九)

文章目录 引言什么是LED点阵屏&#xff1f;工作原理74HC595移位寄存器基本引脚作用级联工作原理 电路图代码演示——16*16LED点阵屏轮播点亮每行LED代码演示——显示数字0代码演示——16*16游动字幕显示 引言 LED点阵屏作为一种广泛应用于现代显示技术的设备&#xff0c;因其能…

Linux_线程的使用

目录 1、线程与进程的关系 2、线程的优缺点 3、创建线程 4、查看启动的线程 5、验证线程是共享地址空间的 6、pthread_create的重要形参 6.1 线程id 6.2 线程实参 7、线程等待 8、线程退出 9、线程取消 10、线程tcb 10.1 线程栈 11、创建多线程 12、__th…

学生信息管理系统设计

学生信息管理系统的设计是一个综合性的项目&#xff0c;涉及到数据的存储、检索、更新和删除等基本操作&#xff0c;同时也需要考虑系统的易用性、安全性和扩展性。以下是一些关键步骤和要素&#xff0c;用于指导设计这样一个系统&#xff1a; 1. 需求分析 目标用户&#xff…

wls2下的centos使用桥接模式连接宿主机网络独立静态ip

前提&#xff1a;wsl2已安装&#xff0c;可正常更新 1.在控制面板中&#xff0c;打开开启或关闭windows功能&#xff0c;将里面的 Hyper-V功能打开&#xff0c;此处涉及重启 2. 按一下win键&#xff0c;输入hy&#xff0c;上面可以看到Hyper-V Manager,点进去 3.选择右边的 Vi…

Redis系列命令更新--Redis有序集合命令

Redis有序集合&#xff08;sorted set&#xff09; &#xff08;1&#xff09;说明&#xff1a; A、Redis有序集合和集合一样也是string类型元素的集合&#xff0c;且不允许重复的成员&#xff1b;不同的是每个元素都会关联一个double类型的分数&#xff1b;redis正式通过分数…

Java语言程序设计——篇五(1)

数组 概述数组定义实例展示实战演练 二维数组定义数组元素的使用数组初始化器实战演练&#xff1a;矩阵计算 &#x1f4ab;不规则二维数组实战演练&#xff1a;杨辉三角形 概述 ⚡️数组是相同数据类型的元素集合。各元素是有先后顺序的&#xff0c;它们在内存中按照这个先后顺…

【ProtoBuf】通讯录实现(网络版)

Protobuf 还常用于通讯协议、服务端数据交换场景。那么在这个示例中&#xff0c;我们将实现一个网络版本的通讯录&#xff0c;模拟实现客户端与服务端的交互&#xff0c;通过 Protobuf 来实现各端之间的协议序列化。 需求如下&#xff1a; 客户端可以选择对通讯录进行以下操…

电脑文件恢复哪个好?分享四个建议记住常备的方法!

当我们发现电脑误删文件的时候&#xff0c;一定会感到焦虑和困惑&#xff0c;但是一味地焦虑和困惑是没有任何帮助的。我们需要保持冷静&#xff0c;然后通过以下几个方法找回。 电脑文件恢复的方法有很多&#xff0c;选对适合自己的数据恢复软件很重要&#xff0c;本文罗列了几…

引领小模型潮流!OpenAI发布功能强大且成本低的GPT-4o mini

GPT-4o mini的成本比GPT-3.5 Turbo低了超过60%&#xff0c;其聊天表现优于Google的Gemini Flash和Anthropic的Claude Haiku。该模型从周四开始对ChatGPT的免费用户、ChatGPT Plus用户和团队订阅用户开放&#xff0c;并将在下周向企业用户开放。OpenAI计划未来将图像、视频和音频…

Linux——五种IO模型

目录 一、I/O的理解 二、五种IO模型 1.阻塞式IO 2.非阻塞式IO 3.信号驱动IO 4.多路复用IO 5.异步IO 一、I/O的理解 I/O的本质就是输入输出&#xff0c;C语言的stdio&#xff0c;C的iostream&#xff0c;添加了这两个库&#xff0c;我们才能够进行printf、scanf、cin、c…

UDP网口(1)概述

文章目录 1.计算机网络知识在互联网中的应用2.认识FPGA实现UDP网口通信3.FPGA实现UDP网口通信的方案4.FPGA实现UDP网口文章安排5.传送门 1.计算机网络知识在互联网中的应用 以在浏览器中输入淘宝网为例&#xff0c;介绍数据在互联网是如何传输的。我们将要发送的数据包称作A&a…

人工智能AI合集:1、嵌入式LinuxAI开发套件OrangePI AIPRO初体验

前言 随着人工智能技术的飞速发展&#xff0c;AI已经不再是遥不可及的高科技概念&#xff0c;而是逐渐融入到我们的日常生活中。从智能手机的语音助手到家庭中的智能音箱&#xff0c;再到工业自动化和医疗诊断&#xff0c;AI的应用无处不在。然而&#xff0c;要想真正掌握并应用…

数学建模学习(111):改进遗传算法(引入模拟退火、轮盘赌和网格搜索)求解JSP问题

文章目录 一、车间调度问题1.1目前处理方法1.2简单案例 二、基于改进遗传算法求解车间调度2.1车间调度背景介绍2.2遗传算法介绍2.2.1基本流程2.2.2遗传算法的基本操作和公式2.2.3遗传算法的优势2.2.4遗传算法的不足 2.3讲解本文思路及代码2.4算法执行结果&#xff1a; 三、本文…

基于java的设计模式学习

PS &#xff1a;以作者的亲身来看&#xff0c;这东西对于初学者来说有用但不多&#xff0c;这些东西&#xff0c;更像一种经验的总结&#xff0c;在平时开发当中一般是用不到的&#xff0c;因此站在这个角度上用处不大。 1.工厂模式 1.1 简单工厂模式 我们把new 对象逻辑封装…

SpringBoot缓存注解使用

背景 除了 RedisTemplate 外&#xff0c; 自Spring3.1开始&#xff0c;Spring自带了对缓存的支持。我们可以直接使用Spring缓存技术将某些数据放入本机的缓存中&#xff1b;Spring缓存技术也可以搭配其他缓存中间件(如Redis等)进行使用&#xff0c;将某些数据写入到缓存中间件…

【Linux】信号(signal)

目录 一、信号概念&#xff1a; 二、信号的常见状态&#xff1a; 信号递达&#xff1a; 信号未决&#xff1a; 阻塞信号&#xff1a; 忽略信号&#xff1a; 信号在内核中的表示&#xff1a; 三、信号相关函数&#xff1a; sigset_t &#xff08;类型&#xff09;&…

2024.7.19 作业

1.链表的排序 int list_sort(NodePtr L) {if(NULLL || L->len<1){printf("排序失败");return -1;}int lenL->len1;NodePtr p;int i,j;for( i1;i<len;i){for( j0,pL;j<len-i;j,pp->next){if( p->data > p->next->data ){datatype tp-&…

基于51单片机的步进电机控制系统proteus仿真

地址&#xff1a;https://pan.baidu.com/s/1jFlIJ9I5qxjW8sYKd6vrBQ?pwd9d6q 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMic…

阿里开源的音频模型_原理与实操

英文名称: FunAudioLLM: Voice Understanding and Generation Foundation Models for Natural Interaction Between Humans and LLMs 中文名称: FunAudioLLM: 人与LLMs之间自然互动的语音理解和生成基础模型 论文地址: http://arxiv.org/abs/2407.04051v3 相关论文&#xff1a;…