SpringBoot集成 Resilience4j,解决大量请求情况下的过载问题

Resilience4j限流的应用场景

1. 微服务架构中的 API 网关

在微服务架构中,API 网关是客户端与各个微服务之间的唯一入口点。通过在 API 网关层使用 Resilience4j 进行限流,可以有效控制进入系统的请求速率,防止后端服务过载。

优点

  • 集中管理:所有流量经过网关,便于统一管理和配置。
  • 减少负载:保护后端服务不被过多请求压垮。
  • 提高可用性:通过限流确保系统稳定运行。

2. 单体应用中的关键接口

即使是在单体应用中,某些关键接口也可能面临高并发请求的压力。通过在这些接口上使用 Resilience4j 进行限流,可以有效控制请求速率,避免系统崩溃。

优点

  • 保护关键资源:确保关键业务逻辑不受过多请求影响。
  • 提升用户体验:在高并发情况下保持良好的响应速度。
  • 简化代码:无需在每个地方单独实现限流逻辑。

3. 第三方 API 调用

当你需要调用第三方 API 时,通常会受到对方的限流策略限制。通过在自己的应用中使用 Resilience4j 进行限流,可以更好地管理对第三方 API 的调用频率,避免触发对方的限流机制。

优点

  • 遵守协议:确保遵循第三方 API 的使用条款和限制。
  • 减少错误:避免因频繁调用导致的 HTTP 429 错误(Too Many Requests)。
  • 优化性能:合理分配请求速率,提高整体性能。

4. 内部服务间的通信

在复杂的系统中,多个服务之间可能存在相互调用的情况。通过在服务间通信的关键路径上使用 Resilience4j 进行限流,可以有效控制请求速率,防止服务之间的互相干扰。

优点

  • 隔离故障:防止一个服务的问题扩散到其他服务。
  • 提高稳定性:确保每个服务都能在其设计容量内正常工作。
  • 简化监控:更容易监控和调试服务间的交互。

5. 批量处理任务

在批处理任务中,可能会有大量的数据需要处理。通过使用 Resilience4j 进行限流,可以控制任务的执行速率,避免对数据库或其他资源造成过大压力。

优点

  • 资源保护:防止数据库或外部资源过载。
  • 提高效率:通过合理的限流策略,提高批处理任务的整体效率。
  • 降低风险:减少因过高负载导致的数据损坏或丢失的风险。

6. 实时数据处理

在实时数据处理系统中,如消息队列消费者、事件驱动架构等,通过使用 Resilience4j 进行限流,可以控制消息消费的速度,避免消费者处理能力不足导致的消息积压。

优点

  • 防止积压:确保消费者能够及时处理消息,避免消息队列积压。
  • 提高吞吐量:通过合理的限流策略,提高系统的吞吐量。
  • 增强可靠性:确保系统的可靠性和稳定性,减少数据丢失的风险。

7. 用户请求控制

对于面向用户的 Web 应用程序,可以通过 Resilience4j 对用户请求进行限流,防止恶意攻击或滥用。

优点

  • 安全防护:防止 DDoS 攻击和其他恶意行为。
  • 用户体验:在高并发情况下保持良好的用户体验。
  • 合规性:符合法律法规对用户请求频率的要求。

8. 分布式系统中的协调服务

在分布式系统中,协调服务(如配置中心、注册中心等)往往扮演着关键角色。通过使用 Resilience4j 进行限流,可以控制对这些服务的访问频率,确保其稳定运行。

优点

  • 稳定性保障:确保协调服务不会因为过度访问而崩溃。
  • 高效协作:提高分布式系统各组件之间的协作效率。
  • 故障隔离:防止局部故障扩散到整个系统。

9. 物联网设备管理

在物联网(IoT)系统中,大量的传感器和设备会产生大量数据。通过使用 Resilience4j 进行限流,可以控制数据上传和处理的速率,避免系统过载。

优点

  • 资源利用:合理利用有限的网络带宽和计算资源。
  • 数据完整性:确保数据传输的完整性和准确性。
  • 系统扩展:支持更多的 IoT 设备连接和数据处理。

10. 机器学习模型推理

在机器学习模型推理过程中,通过使用 Resilience4j 进行限流,可以控制模型推理的请求速率,避免服务器资源耗尽。

优点

  • 资源保护:防止服务器因为过多请求而过载。
  • 性能优化:合理分配资源,提高模型推理的效率。
  • 可靠性:确保模型推理服务的稳定性和可靠性。

代码实操

SpringBoot集成 Resilience4j 来实现细粒度的限流控制

添加依赖

确保你的 pom.xml 文件包含以下依赖:

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Resilience4j Rate Limiter -->
    <dependency>
        <groupId>io.github.resilience4j</groupId>
        <artifactId>resilience4j-ratelimiter-spring-boot2</artifactId>
        <version>1.7.0</version>
    </dependency>

    <!-- Resilience4j Spring Boot2 -->
    <dependency>
        <groupId>io.github.resilience4j</groupId>
        <artifactId>resilience4j-spring-boot2</artifactId>
        <version>1.7.0</version>
    </dependency>

    <!-- Spring Boot Starter AOP -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

    <!-- Spring Boot Starter Test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

配置限流规则

在 application.yml 文件中配置 Resilience4j 的限流规则。

application.yml:

server:
  port:8080

resilience4j:
ratelimiter:
    instances:
      exampleRateLimiter:
        limitForPeriod:5# 每秒允许的最大请求数
        limitRefreshPeriod:1s# 刷新周期为1秒
        timeoutDuration:0# 超时时间为0,表示立即返回结果

创建控制器并使用限流注解

创建一个控制器类,并使用 @RateLimiter 注解来限制请求速率。

ExampleController.java:

package com.example.resilience4jratelimiting;

import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
publicclass ExampleController {

    privatestaticfinal Logger logger = LoggerFactory.getLogger(ExampleController.class);

    @GetMapping("/hello")
    @RateLimiter(name = "exampleRateLimiter", fallbackMethod = "fallback")
    public String sayHello() {
        logger.info("Executing hello endpoint");
        return"Hello, World!";
    }

    public String fallback(Throwable t) {
        logger.warn("Fallback method called due to rate limiting", t);
        return"Too many requests, please try again later.";
    }
}

启动应用程序

在主类上添加 @EnableScheduling 和 @EnableSchedulerLock 注解,虽然在这个例子中我们不需要调度和锁,但这是为了演示完整的配置。

Resilience4jRateLimitingApplication.java:

package com.example.resilience4jratelimiting;

import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
publicclass Resilience4jRateLimitingApplication {

    public static void main(String[] args) {
        SpringApplication.run(Resilience4jRateLimitingApplication.classargs);
    }
}

测试限流

启动应用程序后,我们可以使用 curl 或 Postman 来测试限流效果。

启动应用程序

mvn spring-boot:run

发送请求

打开终端并发送多个请求到 /api/hello 端点。

for i in {1..10}; do curl http://localhost:8080/api/hello; echodone

你将看到以下的输出:

Executing hello endpoint
Hello, World!
Executing hello endpoint
Hello, World!
Executing hello endpoint
Hello, World!
Executing hello endpoint
Hello, World!
Fallback method called due to rate limiting
Too many requests, please try again later.
Fallback method called due to rate limiting
Too many requests, please try again later.
Fallback method called due to rate limiting
Too many requests, please try again later.
Fallback method called due to rate limiting
Too many requests, please try again later.
Fallback method called due to rate limiting
Too many requests, please try again later.

分析测试结果

  • 每秒最多 5 个请求:根据配置,每秒最多允许 5 个请求。
  • 超出限制的请求:超过 5 个请求的响应会被重定向到 fallback 方法,返回 “Too many requests, please try again later.”。

日志分析

查看应用程序的日志,确认限流行为:

2025-01-16 21:23:00.000 INFO  [main] c.e.r.Resilience4jRateLimitingApplication : Starting Resilience4jRateLimitingApplication v0.0.1-SNAPSHOT using Java 11 on hostname with PID 1234 (/path/to/jar started by user)
...
2025-01-16 21:23:05.000 INFO  [nio-8080-exec-1] c.e.r.ExampleController : Executing hello endpoint
2025-01-16 21:23:05.000 INFO  [nio-8080-exec-2] c.e.r.ExampleController : Executing hello endpoint
2025-01-16 21:23:05.000 INFO  [nio-8080-exec-3] c.e.r.ExampleController : Executing hello endpoint
2025-01-16 21:23:05.000 INFO  [nio-8080-exec-4] c.e.r.ExampleController : Executing hello endpoint
2025-01-16 21:23:05.000 INFO  [nio-8080-exec-5] c.e.r.ExampleController : Executing hello endpoint
2025-01-16 21:23:05.000 WARN  [nio-8080-exec-6] c.e.r.ExampleController : Fallback method called due to rate limiting
2025-01-16 21:23:05.000 WARN  [nio-8080-exec-7] c.e.r.ExampleController : Fallback method called due to rate limiting
2025-01-16 21:23:05.000 WARN  [nio-8080-exec-8] c.e.r.ExampleController : Fallback method called due to rate limiting
2025-01-16 21:23:05.000 WARN  [nio-8080-exec-9] c.e.r.ExampleController : Fallback method called due to rate limiting
2025-01-16 21:23:05.000 WARN  [nio-8080-exec-10] c.e.r.ExampleController : Fallback method called due to rate limiting

从日志中可以看到,前 5 个请求成功执行,后续的请求被重定向到 fallback 方法。

测试结果

  • 正常请求:前 5 个请求在一秒内成功执行,返回 “Hello, World!”。
  • 超出限制的请求:第 6 个及以后的请求在一秒内被重定向到 fallback 方法,返回 “Too many requests, please try again later.”。

这证明了 Resilience4j 成功地防止了请求速率超过设定的阈值,达到了限流的目的。

完整代码

你们可以直接拿来自行测试一下。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.5</version>
        <relativePath/><!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>resilience4j-rate-limiting</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>resilience4j-rate-limiting</name>
    <description>Demo project for Resilience4j Rate Limiting</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <!-- Spring Boot Starter Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Resilience4j Rate Limiter -->
        <dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-ratelimiter-spring-boot2</artifactId>
            <version>1.7.0</version>
        </dependency>

        <!-- Resilience4j Spring Boot2 -->
        <dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-spring-boot2</artifactId>
            <version>1.7.0</version>
        </dependency>

        <!-- Spring Boot Starter AOP -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <!-- Spring Boot Starter Test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

application.yml

server:
  port:8080

resilience4j:
ratelimiter:
    instances:
      exampleRateLimiter:
        limitForPeriod:5# 每秒允许的最大请求数
        limitRefreshPeriod:1s# 刷新周期为1秒
        timeoutDuration:0# 超时时间为0,表示立即返回结果

Resilience4jRateLimitingApplication.java

package com.example.resilience4jratelimiting;

import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
publicclass Resilience4jRateLimitingApplication {

    public static void main(String[] args) {
        SpringApplication.run(Resilience4jRateLimitingApplication.classargs);
    }
}

ExampleController.java

package com.example.resilience4jratelimiting;

import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
publicclass ExampleController {

    privatestaticfinal Logger logger = LoggerFactory.getLogger(ExampleController.class);

    @GetMapping("/hello")
    @RateLimiter(name = "exampleRateLimiter", fallbackMethod = "fallback")
    public String sayHello() {
        logger.info("Executing hello endpoint");
        return"Hello, World!";
    }

    public String fallback(Throwable t) {
        logger.warn("Fallback method called due to rate limiting", t);
        return"Too many requests, please try again later.";
    }
}

关注我,送Java福利

/**
 * 这段代码只有Java开发者才能看得懂!
 * 关注我微信公众号之后,
 * 发送:"666"
 * 即可获得一本由Java大神一手面试经验诚意出品
 * 《Java开发者面试百宝书》Pdf电子书
 * 福利截止日期为2025年01月22日止
 * 手快有手慢没!!!
*/
System.out.println("请关注我的微信公众号:");
System.out.println("Java知识日历");



原文始发于微信公众号(Java知识日历):SpringBoot集成 Resilience4j,解决大量请求情况下的过载问题

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/310640.html

(0)
服务端技术精选的头像服务端技术精选

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!