@RateLimiter
时间: 2025-05-13 12:35:27 浏览: 22
### RateLimiter 注解及相关实现
#### 自定义注解的定义
为了实现基于 `RateLimiter` 的限流功能,首先需要定义一个自定义注解。该注解用于标记需要进行限流的服务接口方法。
```java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD) // 限定注解使用范围为方法级别
@Retention(RetentionPolicy.RUNTIME) // 注解在运行时可用
public @interface ExtRateLimiter {
String name(); // 名称,可作为唯一标识符
double permitsPerSecond(); // 每秒允许的最大请求数
}
```
此部分实现了注解的关键字段配置,其中 `permitsPerSecond` 表示每秒允许通过的令牌数[^1]。
---
#### AOP 配置与拦截逻辑
Spring Boot 中可以通过 AOP 技术来拦截带有特定注解的方法,并在其执行前后加入额外的逻辑处理。以下是具体的 AOP 实现:
##### 创建切面类
```java
import com.google.common.util.concurrent.RateLimiter;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Aspect
@Component
public class RateLimiterAspect {
private final Map<String, RateLimiter> rateLimiterMap = new ConcurrentHashMap<>();
@Around("@annotation(extRateLimiter)")
public Object around(ProceedingJoinPoint joinPoint, ExtRateLimiter extRateLimiter) throws Throwable {
String key = extRateLimiter.name();
synchronized (rateLimiterMap) {
if (!rateLimiterMap.containsKey(key)) {
rateLimiterMap.put(key, RateLimiter.create(extRateLimiter.permitsPerSecond()));
}
}
RateLimiter rateLimiter = rateLimiterMap.get(key);
if (rateLimiter.tryAcquire()) { // 尝试获取令牌
return joinPoint.proceed(); // 获取成功则继续执行目标方法
} else {
throw new RuntimeException("Request is limited by rate limiter"); // 获取失败抛出自定义异常
}
}
}
```
上述代码中,`tryAcquire()` 方法尝试从令牌桶中获取令牌。如果无法获取,则触发服务降级逻辑(此处简单地抛出了异常)。
---
#### 使用示例
假设有一个商品购买接口需要进行限流保护,可以按照如下方式标注并调用:
```java
@RestController
@RequestMapping("/product")
public class ProductController {
@ExtRateLimiter(name = "buyProduct", permitsPerSecond = 5)
@PostMapping("/buy/{productId}")
public ResponseEntity<?> buyProduct(@PathVariable Long productId) {
return ResponseEntity.ok("Product purchased successfully");
}
}
```
在此例子中,`/product/buy/{productId}` 接口被设置了每秒最多接受 5 次请求的限制[^3]。
---
#### 改进方案
除了基本的功能外,还可以进一步优化设计:
1. **支持多方法共享同一个限流器**
可以利用 `ConcurrentHashMap` 存储不同名称对应的 `RateLimiter` 对象,从而让多个方法共用同一套限流策略[^2]。
2. **增强失败处理机制**
当无法获取令牌时,可以选择返回默认响应而非直接抛出异常。例如,在 AOP 层面捕获异常并返回友好的提示信息。
3. **扩展限流算法**
Guava 提供了多种限流模式(如平滑突发和平滑预热),可以根据业务需求灵活调整。例如新增注解参数指定每次申请的令牌数量。
---
#### 总结
通过自定义注解配合 Spring AOP 和 Google Guava 的 `RateLimiter` 工具,可以高效地实现接口级别的动态限流功能。这种方式不仅减少了重复代码量,还能显著提升系统的稳定性和可靠性。
---
阅读全文
相关推荐



















