Giter Club home page Giter Club logo

rate-limiter-annotation's Introduction

rate limiter - annotation

Distributed rate limiting simplified using annotations

We believe that rate limiting should be as simple as:

// All methods collectively limited to 10 permits per second
@Rate(10)
class RateLimitedResource {

    // 99 permits per second
    @Rate(99)
    public String smile() {
        return ":)";
    }

    // 2 permits per second only when system available memory is less than 1GB
    @Rate(permits = 2, condition = "jvm.memory.available < 1GB") 
    public String greet(String who) {
        return "Hello " + who;
    }
}

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.8.0</version> 
        </dependency>

Concept

The idea is to be able to rate limit multiple resources fluently and dynamically

class DynamicRateLimiting {

    @Rate(id="resource-a", permits=1)
    static class ResourceA{}
    
    // Will be rate limited when system elapsed time is greater than 59 seconds
    @Rate(id="resource-b", permits=5, condition="sys.time.elapsed > PT59S")
    static class ResourceB{}

    public static void main(String... args) {

        RateLimiterRegistry<String> rateLimiterRegistry = RateLimiterRegistry
                .of(ResourceA.class, ResourceB.class);

        rateLimiterRegistry.getLimiter("resource-a").tryAcquire(); // true
        rateLimiterRegistry.getLimiter("resource-a").tryAcquire(); // false

        rateLimiterRegistry.getLimiter("resource-b").tryAcquire(); // false
    }
}

Sample Usage

import io.github.poshjosh.ratelimiter.RateLimiter;
import io.github.poshjosh.ratelimiter.RateLimiterRegistries;
import io.github.poshjosh.ratelimiter.annotations.Rate;

public class SampleUsage {

    static class RateLimitedResource {

        RateLimiter rateLimiter = RateLimiterRegistries.getLimiter(RateLimitedResource.class,
                "smile");

        // Limited to 3 invocations every second
        @Rate(id = "smile", permits = 3) String smile() {
            if (!rateLimiter.tryAcquire()) {
                throw new RuntimeException("Limit exceeded");
            }
            return ":)";
        }
    }

    public static void main(String... args) {

        RateLimitedResource rateLimitedResource = new RateLimitedResource();

        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.

Bandwidth store

You could use a distributed cache to store Bandwidths. First implement BandwidthStore. The example implementation below uses spring-boot-starter-data-redis

import org.springframework.data.redis.core.RedisTemplate;

public class RedisBandwidthStore implements BandwidthsStore<String> {
    private final RedisTemplate<String, Bandwidth> redisTemplate;
    
    public RedisBandwidthStore(RedisTemplate<String, Bandwidth> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
    
    @Override 
    public Bandwidth get(String key) {
        return redisTemplate.opsForValue().get(key);
    }
    @Override 
    public void put(String key, Bandwidth bandwidth) {
        redisTemplate.opsForValue().set(key, bandwidth);
    }
}

Then use the BandwidthStore as shown below:

public class WithCustomBandwidthStore {
    
    public RateLimiter getRateLimiter(BandwidthsStore store) {
        RateLimiterContext context = RateLimiterContext.builder()
                .classes(MyRateLimitedClass.class)
                .store(store)
                .build();
        return RateLimiterRegistry.of(context).getRateLimiter("ID");
    }
}

Dependents

The following depend on this library:

rate-limiter-annotation's People

Contributors

poshjosh avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.