I'm using these two dependency the code is also shared below , the issue is when I'm trying to run the application for the rate limit everytime I'm consuming the bucket its token is always the same. The expectation is suppose if the refill is set to 2mins and then if I'm consuming for the first time the left token should be 3 , then 2 then 1 and then 429 request.
<bucket4j.starter.version>0.9.1</bucket4j.starter.version><redisson.version>3.24.1</redisson.version>
<dependency>
<artifactId>redisson-spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<artifactId>snakeyaml</artifactId>
<groupId>org.yaml</groupId>
</exclusion>
</exclusions>
<groupId>org.redisson</groupId>
<version>${redisson.version}</version>
</dependency>
<dependency>
<artifactId>bucket4j-spring-boot-starter</artifactId>
<groupId>com.giffing.bucket4j.spring.boot.starter</groupId>
<version>${bucket4j.starter.version}</version>
</dependency>
@Configuration
public class RedisConfig {
@Autowired
private VcapUtils vcapUtils;
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer().setAddress(vcapUtils.getRedisURI());
config.setCodec(new SerializationCodec());
return Redisson.create(config);
}
@Bean
public Config config() {
Config config = new Config();
config.useSingleServer().setAddress(vcapUtils.getRedisURI());
config.setCodec(new SerializationCodec());
return config;
}
@Bean(name = "springCM")
public CacheManager cacheManager(Config config) {
CacheManager cacheManager = Caching.getCachingProvider().getCacheManager();
cacheManager.createCache("rateLimit", RedissonConfiguration.fromConfig(config));
return cacheManager;
}
@Bean
public ProxyManager<String> proxyManager(CacheManager cacheManager) {
return new JCacheProxyManager<>(cacheManager.getCache("rateLimit"));
}
}
@Component
public class RateLimitConfig extends OncePerRequestFilter {
private static final Set<String> URL_TO_BE_IGNORED = Sets.newHashSet(
"/dvh/api/v1/vehicle/$count",
"/dvh/api/v1/vehicle/search",
"/dvh/api/v1/vehicle/attributes"
);
@Autowired
private BucketConfig bucketConfig;
@Autowired
private ProxyManager<String> proxyManager;
private VcapApplication vcapApplication;
@Autowired
public RateLimitConfig() {
this.vcapApplication = VcapApplication.fromEnvironment();
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
Boolean requestURL = URL_TO_BE_IGNORED.contains(request.getRequestURI());
if (Boolean.TRUE.equals(requestURL)) {
filterChain.doFilter(request, response);
return;
}
Bucket bucket = bucketConfig.resolveBucket(SpringSecurityContext.getToken().getZoneId());
ConsumptionProbe probe = bucket.tryConsumeAndReturnRemaining(1);
if (probe.isConsumed()) {
response.setHeader("X-Rate-Limit-Remaining",
String.valueOf(probe.getRemainingTokens()));
filterChain.doFilter(request, response);
} else {
response.setHeader("X-Rate-Limit-Retry-After-Seconds",
String.valueOf(probe.getNanosToWaitForRefill() / 1_000_000_000));
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
}
}
}
@Component
public class BucketConfig {
private static final Logger logger = LoggerFactory.getLogger(BucketConfig.class);
private static final Integer DEFAULT_API_RATE_LIMIT = 4;
private static final Integer REFILL_INTERVAL_IN_SECONDS = 2;
@Autowired
private ProxyManager<String> proxyManager;
public Bucket resolveBucket(String tenantID) {
Supplier<BucketConfiguration> configSupplier = getConfigSupplierForTenant(tenantID);
return proxyManager.builder().build(tenantID, configSupplier);
}
private Supplier<BucketConfiguration> getConfigSupplierForTenant(String tenantID) {
Bandwidth limit = Bandwidth.simple(DEFAULT_API_RATE_LIMIT,
Duration.ofMinutes(REFILL_INTERVAL_IN_SECONDS)).withId(tenantID);
return () -> (BucketConfiguration.builder()
.addLimit(limit)
.build());
}
}
please Note I tried almost everything to make this code work but it didn't , the url and everything is fine and I don't want to go other way like hazelcast or jedis