SpringBoot中基于AOP和Semaphore實現API限流
為了在 Spring Boot 中使用 AOP 實現速率限制:
- 定義自定義注釋來標記應該限速的方法。
- 創(chuàng)建一個方面類,攔截用自定義注釋注釋的方法調用。
- 使用速率限制器組件來跟蹤和執(zhí)行速率限制。
- 處理速率限制超出的情況,如通過拋出自定義異常。
Spring Boot API 中的速率限制
可以使用各種技術在 Spring Boot API 中實現速率限制。一種常見的方法是使用 Spring AOP來攔截傳入的請求并實施速率限制。
步驟 1 - 定義速率限制配置
創(chuàng)建一個配置類,在其中定義速率限制參數,例如允許的請求數和時間段。
@Configuration
public class RateLimitConfig {
@Value("${rate.limit.requests}")
private int requests;
@Value("${rate.limit.seconds}")
private int seconds;
// Getters and setters
}
步驟 2 - 創(chuàng)建速率限制方面
使用 Spring AOP 實現一個方面來攔截方法調用并強制執(zhí)行速率限制。
@Aspect
@Component
public class RateLimitAspect {
@Autowired
private RateLimitConfig rateLimitConfig;
@Autowired
private RateLimiter rateLimiter;
@Around("@annotation(RateLimited)")
public Object enforceRateLimit(ProceedingJoinPoint joinPoint) throws Throwable {
String key = getKey(joinPoint);
if (!rateLimiter.tryAcquire(key, rateLimitConfig.getRequests(), rateLimitConfig.getSeconds())) {
throw new RateLimitExceededException("Rate limit exceeded");
}
return joinPoint.proceed();
}
private String getKey(ProceedingJoinPoint joinPoint) {
//為正在調用的方法生成唯一密鑰
//方法簽名、用戶ID、IP地址等。
}
}
步驟 3 — 定義 RateLimited 注釋
創(chuàng)建自定義注釋來標記應受速率限制的方法。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimited {
}
步驟 4 - 實施速率限制器
創(chuàng)建速率限制器組件,使用令牌桶算法或任何其他合適的算法來管理速率限制。
@Component
public class RateLimiter {
private final Map<String,RateLimitedSemaphore> semaphores = new ConcurrentHashMap<>();
public boolean tryAcquire(String key, int requests, int seconds) {
long currentTime = System.currentTimeMillis();
// 計算時間窗口
long startTime = currentTime - seconds * 1000;
// 過期刪除
cleanupExpiredEntries(startTime);
// 獲取semaphore
RateLimitedSemaphore semaphore = semaphores.computeIfAbsent(key, k -> {
RateLimitedSemaphore newSemaphore = new RateLimitedSemaphore(requests);
newSemaphore.setLastAcquireTime(currentTime); // Set last acquire time
return newSemaphore;
});
// 校驗 semaphore
boolean acquired = semaphore.tryAcquire();
if (acquired) {
semaphore.setLastAcquireTime(currentTime);
// 更新
}
return acquired;
}
private void cleanupExpiredEntries(long startTime) {
Iterator<Map.Entry<String, RateLimitedSemaphore>> iterator = semaphores.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, RateLimitedSemaphore> entry = iterator.next();
String key = entry.getKey();
RateLimitedSemaphore semaphore = entry.getValue();
if (semaphore.getLastAcquireTime() < startTime) {
iterator.remove();
}
}
}
private class RateLimitedSemaphore extends Semaphore {
private volatile long lastAcquireTime;
public RateLimitedSemaphore(int permits) {
super(permits);
}
public long getLastAcquireTime() {
return lastAcquireTime;
}
public void setLastAcquireTime(long lastAcquireTime) {
this.lastAcquireTime = lastAcquireTime;
}
}
}
步驟 5 - 注釋控制器方法
用注解來注釋應該進行速率限制的控制器方法 @RateLimited。
@RestController
public class MyController {
@RateLimited
@GetMapping("/api/resource")
public ResponseEntity<String> getResource() {
// Implementation
}
}
步驟 6 - 配置速率限制屬性
application.properties在您的 或 中配置速率限制屬性 application.yml。
rate.limit.requests=10 rate.limit.seconds=60
要按 IP 地址限制請求,可以從傳入請求中提取 IP 地址并將其用作速率限制的密鑰:
private String getKey(HttpServletRequest request) {
String ipAddress = request.getRemoteAddr();
return ipAddress; //用ID做key
}
還需要修改enforceRateLimit 中的方法 RateLimitAspect 以將對象傳遞 HttpServletRequest 給 getKey 方法:
@Around("@annotation(RateLimited)")
public Object enforceRateLimit(ProceedingJoinPoint joinPoint) throws Throwable {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
String key = getKey(request);
if (!rateLimiter.tryAcquire(key, rateLimitConfig.getRequests(), rateLimitConfig.getSeconds())) {
throw new RateLimitExceededException("Rate limit exceeded");
}
return joinPoint.proceed();
}
以上就是SpringBoot中基于AOP和Semaphore實現API限流的詳細內容,更多關于SpringBoot實現API限流的資料請關注腳本之家其它相關文章!
相關文章
MyBatis使用注解開發(fā)和無主配置文件開發(fā)的情況
這篇文章主要介紹了MyBatis使用注解開發(fā)和無主配置文件開發(fā)的情況,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03
關于Jackson的JSON工具類封裝 JsonUtils用法
這篇文章主要介紹了關于Jackson的JSON工具類封裝 JsonUtils用法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
Spring實戰(zhàn)之ServletContextResource訪問資源文件示例
這篇文章主要介紹了Spring實戰(zhàn)之ServletContextResource訪問資源文件,結合實例形式分析了spring使用ServletContextResource讀取與遍歷資源文件相關操作技巧,需要的朋友可以參考下2019-12-12

