如何使用key-prefix标记方法进行分布式限流控制。
本案例使用Spring Boot框架和 Redis客户端库,可以直接运行并测试接口限流功能。
- 创建一个RateLimitInterceptor拦截器类,在该类中实现接口限流逻辑。
import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;
public class RateLimitInterceptor implements HandlerInterceptor {
private final RedisClient redisClient;
private final String apiPrefix;
private final int rateLimit;
public RateLimitInterceptor(RedisClient redisClient, String apiPrefix, int rateLimit) {
this.redisClient = redisClient;
this.apiPrefix = apiPrefix;
this.rateLimit = rateLimit;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String key = apiPrefix + ":" + request.getRemoteAddr(); // 构造唯一键值
StatefulRedisConnection<String, String> connection = redisClient.connect(); // 获取Redis连接
RedisCommands<String, String> syncCommands = connection.sync(); // 获取Redis命令对象
long count = syncCommands.incr(key); // 计数器加1,并获取当前值
syncCommands.expire(key, 1, TimeUnit.SECONDS); // 设置计数器过期时间为1秒
if (count > rateLimit) { // 如果超出限制则返回错误码
response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
return false;
}
return true;
}
}
- 在Spring Boot的配置文件中添加Redis连接配置信息。
spring:
redis:
host: localhost
port: 6379
- 在启动类中创建RedisClient对象,并注册RateLimitInterceptor拦截器。
import io.lettuce.core.RedisClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@SpringBootApplication
public class MyApp implements WebMvcConfigurer {
@Value("${app.api.prefix}")
private String apiPrefix;
@Value("${app.rate.limit}")
private int rateLimit;
@Bean
public RedisClient redisClient() {
return RedisClient.create("redis://localhost:6379");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new RateLimitInterceptor(redisClient(), apiPrefix, rateLimit));
}
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
- 在Controller中添加一个测试接口。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@GetMapping("/api/test")
public String test() {
return "Hello, world!";
}
}
- 运行并测试接口限流功能。在浏览器中访问测试接口,如果请求次数超过限制,服务器将返回429错误码。
注意:为了保证测试稳定性,建议将限流阈值设置得较低。真实环境下应根据具体情况进行调整,避免过于严格的限流导致正常请求无法访问。
限流阈值(Rate Limit)是指在一段时间内允许通过的最大请求数量。通常用于控制系统的接口访问流量,防止系统被恶意攻击或过度使用而导致负载过高