DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Distributed Rate Limiting in Java: A Deep Dive into Bucket4j + PostgreSQL
  • How to Provide Rate-Limiting Via Bucket4j in Java
  • Getting Started With Agentic Workflows in Java and Quarkus
  • Building AI-Powered Java Applications With Jakarta EE and LangChain4j

Trending

  • Using LLMs to Automate Data Cleaning and Transformation Pipelines
  • Build a GitHub Slack Bot With AWS Bedrock and MCP, Part 2
  • Architecting Zero-Trust AI Agents: How to Handle Data Safely
  • Why DDoS Protection Is an Architectural Decision for Developers
  1. DZone
  2. Coding
  3. Java
  4. Scalable Rate Limiting in Java With Code Examples: Managing Multiple Instances

Scalable Rate Limiting in Java With Code Examples: Managing Multiple Instances

Implement scalable rate limiting in Java using Token Bucket, Redis, and Gradle for high-performance and DoS attack protection.

By 
Arun Pandey user avatar
Arun Pandey
DZone Core CORE ·
Oct. 02, 23 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
11.1K Views

Join the DZone community and get the full member experience.

Join For Free

Rate limiting is an essential technique to control the number of requests a user can send to an application within a specific time frame. It helps protect applications from Denial-of-Service (DoS) attacks, ensures fair usage of resources, and maintains the stability and performance of the system. In this article, we will discuss how to implement scalable rate limiting in Java using multiple instances, complete with code examples and Gradle-based development.

Understanding Rate Limiting

Rate limiting works by setting a limit on the number of requests a user can make within a specific time window. When the limit is reached, the user receives an error message or is temporarily blocked from making further requests. There are several algorithms for implementing rate limiting, such as the Token Bucket and Leaky Bucket algorithms.

Scalability and Multiple Instances

When dealing with high-traffic applications, it's essential to ensure that the rate-limiting solution can handle the increased load and scale accordingly. One way to achieve this is by running multiple instances of the rate-limiting algorithm. This enables the system to distribute the load across different instances, improving its overall performance and efficiency.

Implementing Scalable Rate Limiting in Java

To implement a scalable rate-limiting solution in Java, we will use the Token Bucket algorithm and Redis as a distributed data store.

Token Bucket Algorithm

The Token Bucket algorithm works by adding tokens to a bucket at a specified rate. When a user makes a request, the system checks if there are enough tokens in the bucket. If there are, the request is processed, and the tokens are removed from the bucket. If not, the request is rejected or delayed.

Redis as a Distributed Data Store

Redis is an in-memory data structure store that can be used as a distributed cache. By using Redis, we can store the token buckets in a centralized location, allowing multiple instances of the rate-limiting algorithm to access and update them consistently.

Java Implementation With Gradle

To implement the rate-limiting solution in Java using Gradle, follow these steps:

Step 1: Install and configure Redis on your system.

Step 2: Add the necessary dependencies to your Gradle build file, such as the Redis client library (e.g., Jedis) and a rate-limiting library (e.g., Bucket4j).

Groovy
 
// build.gradle
dependencies {
    implementation 'redis.clients:jedis:3.7.0'
    implementation 'com.github.vladimir-bukhtoyarov:bucket4j:6.0.2'
}


Step 3: Create a class to represent the token bucket and include methods for adding tokens, checking the available tokens, and removing tokens when a request is processed.

Java
 
// TokenBucket.java

import io.github.bucket4j.Bucket;
import io.github.bucket4j.Bucket4j;
import io.github.bucket4j.ConsumptionProbe;

public class TokenBucket {

    private final Bucket bucket;

    public TokenBucket(long capacity, long refillTokens, long refillDurationMillis) {
        this.bucket = Bucket4j.builder()
                .addLimit(capacity, refillTokens, refillDurationMillis)
                .build();
    }

    public boolean tryConsume() {
        ConsumptionProbe probe = bucket.tryConsumeAndReturnRemaining(1);
        return probe.isConsumed();
    }
}


Step 4: Configure the rate-limiting settings, such as the maximum number of tokens, the token refill rate, and the time window.

Java
 
// RateLimiterConfig.java

public class RateLimiterConfig {

    public static final long TOKEN_BUCKET_CAPACITY = 100;
    public static final long TOKEN_REFILL_RATE = 50;
    public static final long REFILL_DURATION_MILLIS = 60_000; // 1 minute
}


Step 5: Use the Redis client to store and manage the token buckets. Ensure that the buckets are updated consistently across all instances.

Java
 
// RedisTokenBucketStore.java

import redis.clients.jedis.Jedis;

public class RedisTokenBucketStore {

    private static final String REDIS_HOST = "localhost";

    private static final int REDIS_PORT = 6379;

    private final Jedis jedis;

    public RedisTokenBucketStore() {

        this.jedis = new Jedis(REDIS_HOST, REDIS_PORT);
    }

    public TokenBucket getTokenBucket(String key) {

        String serializedBucket = jedis.get(key);

        if (serializedBucket == null) {

            TokenBucket newBucket = new TokenBucket(
                    RateLimiterConfig.TOKEN_BUCKET_CAPACITY,
                    RateLimiterConfig.TOKEN_REFILL_RATE,
                    RateLimiterConfig.REFILL_DURATION_MILLIS);
            jedis.set(key, newBucket.toString());
            return newBucket;

        } else {

            // Deserialize the bucket and return it
            // ...
        }
    }

    public void updateTokenBucket(String key, TokenBucket bucket) {

        // Serialize the bucket and store it in Redis
        // ...
    }
}


Step 6: Integrate the rate-limiting solution into your application, ensuring that each incoming request checks the availability of tokens before being processed.

Java
 
// RateLimiterMiddleware.java

public class RateLimiterMiddleware {

    private final RedisTokenBucketStore tokenBucketStore;

    public RateLimiterMiddleware() {

        this.tokenBucketStore = new RedisTokenBucketStore();
    }

    public boolean shouldProcessRequest(String userIdentifier) {

        TokenBucket tokenBucket = tokenBucketStore.getTokenBucket(userIdentifier);
        boolean canProcess = tokenBucket.tryConsume();
        tokenBucketStore.updateTokenBucket(userIdentifier, tokenBucket);
        return canProcess;
    }
}


Conclusion

Implementing a scalable rate-limiting solution in Java using multiple instances and Gradle-based development is an effective way to manage high-traffic applications and ensure their stability and performance. By using the Token Bucket algorithm and Redis as a distributed data store, you can create a robust and scalable rate-limiting solution that can handle the increased load and distribute it across different instances. This approach not only improves the overall performance of your application but also helps protect it from potential DoS attacks and ensures fair usage of resources.

Java (programming language) rate limit

Opinions expressed by DZone contributors are their own.

Related

  • Distributed Rate Limiting in Java: A Deep Dive into Bucket4j + PostgreSQL
  • How to Provide Rate-Limiting Via Bucket4j in Java
  • Getting Started With Agentic Workflows in Java and Quarkus
  • Building AI-Powered Java Applications With Jakarta EE and LangChain4j

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook