在现代的微服务架构中,常常需要对接口进行访问限流、黑名单拦截等操作,以保护后端服务的稳定性和安全性。Spring Boot、Redisson、AOP(面向切面编程)结合自定义注解可以很好地实现这些功能。本文将介绍如何使用这些技术来实现一个简单的访问限流和黑名单拦截机制。
1. 环境准备
首先,我们需要在Spring Boot项目中添加Redisson的依赖。在pom.xml
中添加以下依赖:
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.16.1</version> <!-- 请根据需要选择合适的版本 -->
</dependency>
2. 自定义注解
我们创建两个自定义注解:@RateLimit
用于限流,@Blacklist
用于黑名单拦截。
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 RateLimit {
int limit();
int timeout();
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Blacklist {
}
3. AOP 切面实现
接下来,我们将创建一个AOP切面,用于处理这两个注解的逻辑。
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.Redisson;
import org.redisson.api.RBucket;
import org.redisson.api.RRateLimiter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Aspect
@Component
public class RateLimitAspect {
@Autowired
private Redisson redisson;
@Around("@annotation(rateLimit)")
public Object rateLimit(ProceedingJoinPoint joinPoint, RateLimit rateLimit) throws Throwable {
String key = joinPoint.getSignature().toShortString();
RRateLimiter rateLimiter = redisson.getRateLimiter(key);
rateLimiter.trySetRate(RateType.OVERALL, rateLimit.limit(), rateLimit.timeout(), TimeUnit.SECONDS);
if (!rateLimiter.tryAcquire()) {
throw new RuntimeException("请求过于频繁,请稍后再试!");
}
return joinPoint.proceed();
}
}
@Aspect
@Component
public class BlacklistAspect {
@Autowired
private Redisson redisson;
@Around("@annotation(blacklist)")
public Object blacklist(ProceedingJoinPoint joinPoint) throws Throwable {
String ipAddress = getIpAddress(); // 抽取请求的IP地址
RBucket<Boolean> bucket = redisson.getBucket("blacklist:" + ipAddress);
if (bucket.isExists() && bucket.get()) {
throw new RuntimeException("该IP已被加入黑名单!");
}
return joinPoint.proceed();
}
private String getIpAddress() {
// 这里实现获取IP地址的逻辑
return "127.0.0.1"; // 示例,用实际ip地址获取逻辑替换
}
}
4. 示例Controller
下面是一个示例Controller,演示如何使用我们定义的注解。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/test")
@RateLimit(limit = 5, timeout = 10)
@Blacklist
public String test() {
return "请求成功";
}
}
5. 总结
通过使用Redisson进行分布式锁与限流、AOP技术监控方法调用、以及自定义注解来达到简化代码的目的,我们可以实现一个功能强大的访问限流和黑名单拦截机制。这种实现方式既符合Spring Boot的开发理念,又具有良好的扩展性和维护性。
在真实环境中,我们还可以将黑名单信息存储在Redis中,以实时更新黑名单的数据。同时,可以根据需要扩展限流策略,比如使用滑动时间窗口等复杂算法。希望本文能为你在项目中实现限流和黑名单功能提供帮助。