rate limiter - annotation
Distributed rate limiting simplified using annotations
We believe rate limiting should as easy as:
// All methods collectively limited to 10 permits per second
@Rate(10)
class RateLimitedResource {
// 2 permits per second only when system free memory is less than 1GB
@Rate(2)
@RateCondition("jvm.memory.free<1GB")
@Path("/greet")
public String greet(String who) {
return "Hello " + who;
}
// 50 permits per minute
@Rate(permits = 50, duration = TimeUnit.MINUTES)
@Path("/smile")
public String smile() {
return ":)";
}
}
Based on rate-limiter.
Please first read the rate-limiter documentation.
For flexibility, this library offers a robust support for annotations.
If the target is web applications, consider using any of:
To add a dependency on rate-limiter-annotation
using Maven, use the following:
<dependency>
<groupId>io.github.poshjosh</groupId>
<artifactId>rate-limiter-annotation</artifactId>
<version>0.5.0</version>
</dependency>
Concept
Unlike RateLimiter
, ResourceLimiter
introduces the concept of resources. One ResourceLimiter
could be used to rate limit multiple resources distributed across different machines.
import java.util.Arrays;
class Concept {
@Rate(name="resource-a", permits=1)
static class ResourceA{}
@Rate(name="resource-b", permits=5)
static class ResourceB{}
public static void main(String... args) {
List<Class<?>> resourceClasses = Arrays.asList(ResourceA.class, ResourceB.class);
ResourceLimiter<String> resourceLimiter = ResourceLimiter.of(resourceClasses);
resourceLimiter.tryConsume("resource-a"); // true
resourceLimiter.tryConsume("resource-a"); // false
resourceLimiter.tryConsume("resource-b"); // false
}
}
Sample Usage
import io.github.poshjosh.ratelimiter.ResourceLimiter;
import io.github.poshjosh.ratelimiter.annotations.Rate;
public class SampleUsage {
static class RateLimitedResource {
final ResourceLimiter<String> resourceLimiter;
RateLimitedResource(ResourceLimiter<String> resourceLimiter) {
this.resourceLimiter = resourceLimiter;
}
// Limited to 3 invocations every second
@Rate(name = "smile", permits = 3)
String smile() {
if (!resourceLimiter.tryConsume("smile")) {
throw new RuntimeException("Limit exceeded");
}
return ":)";
}
}
public static void main(String... args) {
ResourceLimiter<String> resourceLimiter = ResourceLimiter.of(RateLimitedResource.class);
RateLimitedResource rateLimitedResource = new RateLimitedResource(resourceLimiter);
int i = 0;
for(; i < 3; i++) {
System.out.println("Invocation " + i + " of 3 should succeed");
rateLimitedResource.smile();
}
System.out.println("Invocation " + i + " of 3 should fail");
rateLimitedResource.smile();
}
}
Annotation Specification
Please read the annotation specs. It is concise.
Dependents
The following depend on this library: