使用 Spring AOP 和 Guava RateLimiter 实现 API 限流

news/2025/2/11 23:27:24/

在高并发的应用场景下,合理的限流策略是保证系统稳定性的重要手段之一。限流可以防止系统资源被耗尽,避免雪崩效应的发生。本文将介绍如何使用 Spring AOP 和 Guava RateLimiter 实现API限流,并支持自定义限流超时时间。

引入依赖

首先,需要在 pom.xml 中引入 Guava 依赖:

<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>31.1-jre</version>
</dependency>

定义注解

其次,定义一个 @ApiRateLimit 注解,在需要限流的方法上标注该注解:

java">import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ApiRateLimit {double qps() default 1; // 每秒钟生成令牌的速率long timeout() default 0; // 尝试获取令牌的超时时间TimeUnit timeUnit() default TimeUnit.SECONDS; // 超时时间单位
}
  • qps 参数控制每秒生成令牌数,即控制限流速率
  • timeouttimeUnit 参数控制获取令牌的超时时间,0表示无超时

实现切面

接下来实现 ApiRateLimitAspect 切面类,在方法执行前通过 RateLimiter 判断是否被限流:

java">import com.google.common.util.concurrent.RateLimiter;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;@Aspect
@Component
public class ApiRateLimitAspect {private final Map<String, RateLimiter> rateLimiters = new ConcurrentHashMap<>();@Before("@annotation(apiRateLimit)")public void limit(JoinPoint joinPoint, ApiRateLimit apiRateLimit) {String methodName = joinPoint.getSignature().toLongString();double qps = apiRateLimit.qps();RateLimiter limiter = rateLimiters.computeIfAbsent(methodName, k -> RateLimiter.create(qps));long timeout = apiRateLimit.timeout();TimeUnit timeUnit = apiRateLimit.timeUnit();if (timeout > 0) {if (!limiter.tryAcquire(timeout, timeUnit)) {throw new RuntimeException("API rate limit exceeded");}} else {if (!limiter.tryAcquire()) {throw new RuntimeException("API rate limit exceeded");}}}
}
  • 使用 ConcurrentHashMap 缓存每个方法对应的 RateLimiter 实例
  • 根据 @ApiRateLimit 注解的参数尝试获取令牌
    • 若超时时间大于0,使用 tryAcquire(timeout, timeUnit) 获取令牌
    • 若超时时间为0,使用 tryAcquire() 获取令牌
  • 如果无法获取令牌,抛出 RuntimeException 限流异常

使用示例

在 Controller 方法上标注 @ApiRateLimit 注解即可实现限流:

java">@RestController
public class DemoController {@GetMapping("/test")@ApiRateLimit(qps = 2, timeout = 200, timeUnit = TimeUnit.MILLISECONDS)public String test() {return "hello world";}
}

上述代码对 /test 接口限流,限流速率为每秒 2 个请求,获取令牌超时时间为 200 毫秒。

总结

通过简单的注解和 AOP 切面,就可以实现 API 限流功能,并支持自定义限流速率和限流超时时间。这种实现方式无侵入性,添加或移除限流只需要在方法上增加或移除注解即可,降低了维护成本。

值得注意的是,在分布式环境下,单机限流的方式可能无法满足需求,我们需要结合分布式限流组件如 Redis 等来实现全局限流。另外,限流策略也可以根据实际场景进行优化,如配合熔断、降级等策略使用,以提高系统的稳定性。


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

相关文章

面试题集中营—分布式共识算法

分布式共识算法目标 分布式主要就是为了解决单点故障。一开始只有一个服务节点提供服务&#xff0c;如下图所示。那么如果服务节点挂了&#xff0c;对不起等着吧。 为了服务的高可用性&#xff0c;我们一般都会多引入几个副节点当备份&#xff0c;当服务节点挂了&#xff0c;就…

什么是三高架构

三高架构是指在软件系统设计与开发中&#xff0c;注重解决高并发性、高可用性和高性能的架构设计模式。 高并发性&#xff1a;指系统能够处理大量并发请求的能力。在高并发场景下&#xff0c;系统需要具备有效的并发处理机制&#xff0c;以保证系统能够快速、准确地响应大量并…

【设计模式】组合模式

目录 什么是组合模式 代码实现 什么是组合模式 Java中的组合模式&#xff08;Composite Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许将对象组合成树形结构以表示部分-整体的层次结构。组合模式使得客户端对单个对象和组合对象的处理具有一致性&#xff0c;因…

python-selenium +Chrome driver环境配置

selenium Chrome driver环境配置_chromedriver 122.0.6261.112-CSDN博客

移植speexdsp到OpenHarmony标准系统②

在linux上生成speexdsp的so动态链接库和.a静态链接库 make和make install后会生成speexdsp的.so动态链接库和.a静态链接库 make make install其中build/lib目录下&#xff1a; ├── libspeexdsp.a /*静态库*/ ├── libspeexdsp.la …

Kafka入门介绍+集群部署+简单使用

Kafka入门介绍集群部署简单使用 简介核心概念Broker&#xff08;服务节点/实例&#xff09;Producer&#xff08;生产者&#xff09;Topic&#xff08;主题&#xff09;Partition&#xff08;分区&#xff09;Consumer&#xff08;消费者&#xff09;和Consumer Group&#xff…

c#多线程 使用lock锁

使用 lock 关键字可以确保在同一时刻只有一个线程可以访问被锁定的代码块&#xff0c;从而避免线程资源竞争。以下是修改后的示例代码&#xff1a; using System; using System.Threading;class Program {static int sharedNumber 0;static int iterations 1000000;static o…

URL地址解析至页面展示全过程(面试详细解答)

目录 1、解析URL 2、缓存判断 ​编辑3、DNS解析 ​编辑4、获取MAC地址 5、TCP三次握手 6、HTTP请求 7、服务器处理请求&#xff0c;返回HTTP响应 8、页面渲染 9、TCP四次挥手 10、浏览器解析HTML 11、浏览器布局渲染 1、解析URL 首先会对 URL 进行解析&#xff0c;…