提问1:spring boot 实现单个用户访问接口限流的方法 一分钟内限制20次 可以使用别的框架
回答如下:
可以使用Spring Cloud Gateway和Redis实现单个用户访问接口限流的方法,具体步骤如下:
添加依赖 在Spring Boot项目的pom.xml文件中添加以下依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置Redis 在application.yml文件中添加Redis的连接配置:
spring:
redis:
host: localhost
port: 6379
配置限流过滤器 在Spring Cloud Gateway中添加限流过滤器,该过滤器可以通过Redis记录用户访问次数和访问时间,实现单个用户访问接口限流的功能。具体代码如下:
配置限流过滤器的Bean 在Spring Boot项目中,将限流过滤器配置为一个Bean:
public class RateLimiterFilter implements GatewayFilter, Ordered {
private RedisTemplate<String, String> redisTemplate;
@Autowired
public RateLimiterFilter(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
String key = "rate_limiter:" + ip;
String count = redisTemplate.opsForValue().get(key);
if (count == null) {
redisTemplate.opsForValue().set(key, "1", Duration.ofMinutes(1));
} else {
int cnt = Integer.parseInt(count);
if (cnt >= 20) {
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
return exchange.getResponse().setComplete();
} else {
redisTemplate.opsForValue().increment(key);
}
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1;
}
}
@Configuration
public class GatewayConfig {
@Bean
public RateLimiterFilter rateLimiterFilter(RedisTemplate<String, String> redisTemplate) {
return new RateLimiterFilter(redisTemplate);
}
}
测试限流效果 通过postman等工具发送20次以上的请求后,将会返回状态码429,表示访问过于频繁。 以上就是使用Spring Cloud Gateway和Redis实现单个用户访问接口限流的方法。
提问2:不使用spring-cloud-starter-gateway ,保留redis的呢?
回答:
如果不使用Spring Cloud Gateway,可以通过拦截器实现单个用户访问接口限流的功能,具体步骤如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置Redis 在application.yml文件中添加Redis的连接配置:
spring:
redis:
host: localhost
port: 6379
配置拦截器 在Spring Boot项目中添加一个拦截器,该拦截器可以通过Redis记录用户访问次数和访问时间,实现单个用户访问接口限流的功能。具体代码如下:
@Component
public class RateLimiterInterceptor implements HandlerInterceptor {
private RedisTemplate<String, String> redisTemplate;
@Autowired
public RateLimiterInterceptor(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String ip = request.getRemoteAddr();
String key = "rate_limiter:" + ip;
String count = redisTemplate.opsForValue().get(key);
if (count == null) {
redisTemplate.opsForValue().set(key, "1", Duration.ofMinutes(1));
} else {
int cnt = Integer.parseInt(count);
if (cnt >= 20) {
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
return false;
} else {
redisTemplate.opsForValue().increment(key);
}
}
return true;
}
}
配置拦截器的Bean 在Spring Boot项目中,将拦截器配置为一个Bean:
@Configuration
public class WebConfig implements WebMvcConfigurer {
private final RateLimiterInterceptor rateLimiterInterceptor;
@Autowired
public WebConfig(RateLimiterInterceptor rateLimiterInterceptor) {
this.rateLimiterInterceptor = rateLimiterInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(rateLimiterInterceptor)
.addPathPatterns("/**");
}
}
测试限流效果 通过postman等工具发送20次以上的请求后,将会返回状态码429,表示访问过于频繁。 以上就是使用拦截器和Redis实现单个用户访问接口限流的方法。