Learnitweb

Implementing Redis Rate Limiter in Spring Boot Gateway Server

Introduction

Rate limiting is a crucial aspect of API security and performance. It prevents abuse, ensures fair usage, and protects backend services from being overwhelmed by excessive requests. In this tutorial, we will implement a Redis-based rate limiter in a Spring Boot Gateway server.

Dependency

Add the following dependency to the pom.xml:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
    </dependency>

Configuring redis rate limiter

Add the following two beans:

@Bean
	public RedisRateLimiter redisRateLimiter() {
		return new RedisRateLimiter(1, 1, 1);
	}

	@Bean
	KeyResolver userKeySolver() {
		return exchange -> Mono.justOrEmpty(exchange.getRequest().getHeaders().getFirst("user"))
				.defaultIfEmpty("anonymous");
	}

Add the requestRateLimiter:

@Bean
	public RouteLocator eshopAppRouterConfig(RouteLocatorBuilder routeLocatorBuilder) {
		return routeLocatorBuilder.routes().route(p -> p.path("/eshop/productservice/**")
				.filters(f -> f.rewritePath("/eshop/productservice/(?<segment>.*)", "/${segment}").requestRateLimiter(
						config -> config.setRateLimiter(redisRateLimiter()).setKeyResolver(userKeySolver())))

				.uri("lb://PRODUCTSERVICE")).build();
	}

The redisRateLimiter bean defines a Redis-based rate limiter.

The parameters (1, 1, 1) correspond to:

  • Replenish Rate: 1 → Number of requests added per second.
  • Burst Capacity: 1 → Maximum number of requests allowed in a burst.
  • Requested Tokens: 1 → Number of tokens required for each request.

The userKeySolver defines a KeyResolver that extracts a unique key for rate limiting. It reads the "user" header from the HTTP request. If the header is missing, it defaults to "anonymous". The KeyResolver determines which key to use for rate limiting. This key is used in Redis to track API requests per user.

Add the following under spring:

data:
    redis:
        connect-timeout: 2s
        host: localhost
        port: 6379
        timeout: 1s

Starting the redis

Use the following docker command to run the redis:

docker run -p 6379:6379 --name eazyredis -d redis

Testing the code

You can use Apache bench to send multiple requests. If a request exceeds the limit, it is rejected with an HTTP 429 (Too Many Requests).

To Read

Read about the BulkHead Pattern and it’s implementation using Resilience4j

https://resilience4j.readme.io/docs/bulkhead