Reputation: 126
I am using "com.giffing.bucket4j.spring.boot.starter" to implement ratelimit using hazelcast in my spring cloud project.
The bucket4j is not getting initialized on the application startup. Due to this the rate limiting is not working.
My project has limitation to use 3.1.2 spring boot version and as per the bucket4j giffing documentation I am using 0.10.3 version of bucket4j starter. But the rate limit is not working.
Please help.
Complete code base:
GatewaySampleApplication.java
package com.oardic.springbootbucket4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableCaching
public class GatewaySampleApplication {
public static void main(String[] args) {
SpringApplication.run(GatewaySampleApplication.class, args);
}
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
//@formatter:off
return builder.routes()
.route(p -> p
.path("/get")
.filters(f -> f.addRequestHeader("Hello", "World"))
.uri("http://httpbin.org:80"))
.build();
//@formatter:on
}
}
MyController.java
package com.oardic.springbootbucket4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping
public class MyController {
@GetMapping("/hello")
public Mono<String> hello(
@RequestParam(defaultValue = "World") String name) {
return Mono.just("Hello")
.flatMap(s -> Mono
.just(s + ", " + name + "!\n")
);
}
@GetMapping("/world")
public Mono<String> world(
@RequestParam(defaultValue = "World") String name) {
return Mono.just("Hello")
.flatMap(s -> Mono
.just(s + ", " + name + "!\n")
);
}
}
application.yml
spring:
cache:
type: jcache
jcache:
provider: com.hazelcast.cache.impl.HazelcastServerCachingProvider
config: classpath:hazelcast.xml
management:
endpoints:
web:
exposure:
include: "*"
bucket4j:
cache-to-use: hazelcast
enabled: true
filters:
- cache-name: buckets
rate-limits:
- bandwidths:
- capacity: 1
time: 5
unit: seconds
cache-key: '@securityService.getClientIP(#this)'
url: /myservice/endpoint/*
debug: true
logging:
file:
name: temp.log
path: D://temp.log
hazelcast.xml
<?xml version="1.0" encoding="UTF-8"?>
<hazelcast xmlns="http://www.hazelcast.com/schema/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.hazelcast.com/schema/config
http://www.hazelcast.com/schema/config/hazelcast-config-4.1.xsd">
<map name="buckets">
<time-to-live-seconds>120</time-to-live-seconds>
<in-memory-format>BINARY</in-memory-format>
<metadata-policy>CREATE_ON_UPDATE</metadata-policy>
<statistics-enabled>true</statistics-enabled>
</map>
<cache name="buckets">
</cache>
</hazelcast>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.2</version>
<relativePath />
</parent>
<groupId>com.giffing.bucket4j.spring.boot.starter</groupId>
<artifactId>bucket4j-spring-boot-starter-example-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2022.0.3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.giffing.bucket4j.spring.boot.starter</groupId>
<artifactId>bucket4j-spring-boot-starter</artifactId>
<version>0.10.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
</dependency>
<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<artifactId>bucket4j-hazelcast</artifactId>
<version>7.6.0</version>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Upvotes: 0
Views: 179
Reputation: 126
Firstly giffing 0.10.3 doesnot have the required Async and Sync cache resolvers for hazelcast. Hence upgrading the griffing jar is required. For more info, you can check the PRs for this griffing repo.
Issue resolved with adding the updated spring boot starter bucket4j which is having async resolvers and also added buket4j related jars. bucket4j-hazelcast:com.bucket4j:8.10.1 and griffing 0.12.8 jars also use cache-to-use property to hazelcast-spring or hazelcast-reactive based on requirement.
Make sure the bucket4j dependecies are present in both hazelcast client and server.
Also when combined with this gateway, need to mandatorily include filter-method to WEBFLUX to register the filter with spring.
also use below props.
bucket4j.filters[1].filter-method=WEBFLUX
bucket4j.filters[1].cache-name=buckets
bucket4j.filters[1].url=^(/gateway/service).*
bucket4j.filters[1].rate-limits[0].bandwidths[0].capacity=10
bucket4j.filters[1].rate-limits[0].bandwidths[0].time=60
bucket4j.filters[1].rate-limits[0].bandwidths[0].unit=seconds
bucket4j.filters[1].rate-limits[0].bandwidths[0].refill-speed=interval
spring.cache.type=jcache
spring.cache.jcache.provider=com.hazelcast.client.cache.HazelcastClientCachingProvider
Upvotes: 0