Microservices Based System with API Gateway and Rate Limiting in Java

2 min read

Microservices Based System with API Gateway and Rate Limiting in Java

In modern application architectures, microservices provide scalability, modularity, and ease of development. To manage communication between services and ensure security, an API Gateway is introduced as the single entry point for all client requests. Moreover, to protect backend services from overload and ensure fair usage, rate limiting is implemented.

This article discusses the system design of a microservices-based architecture using an API Gateway with rate limiting, implemented in Java, along with code examples.

Key Components of the System

  1. Client:
    • This could be a web application, mobile application, or any service that consumes APIs.
  2. API Gateway:
    • Acts as the single point of entry for all client requests.
    • Handles tasks such as request routing, rate limiting, authentication, and response aggregation.
  3. Microservices:
    • Independent services such as User Service, Order Service, and Payment Service. Each focuses on a specific functionality and has its own database.
  4. Rate Limiting:
    • Protects the backend services by limiting the number of requests a client can make within a time window.
  5. Database:
    • Each microservice has its own database to ensure data isolation and service independence.
  6. Monitoring and Logging:
    • Provides insights into request patterns and system performance.

High-Level Architecture

+-------------------+
|    Client         |
| (Web/Mobile App)  |
+--------+----------+
         |
         | HTTP/REST
         v
+-------------------+
|    API Gateway    |
| - Rate Limiting   |
| - Routing         |
+--------+----------+
         |
  +------+-----+--------+
  |             |        |
+v-----+    +--v----+ +--v----+
| User |    | Order  | |Payment|
|Service|   |Service | |Service|
+-------+   +--------+ +-------+

Step-by-Step Implementation

Step 1: Setting Up the API Gateway

Use Spring Cloud Gateway as the API Gateway. It provides features like routing, rate limiting, and request/response filters.

Add dependencies in pom.xml:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

Configure routes in application.yml:

spring:
  cloud:
    gateway:
      routes:
        - id: user_service
          uri: http://localhost:8081
          predicates:
            - Path=/users/**
        - id: order_service
          uri: http://localhost:8082
          predicates:
            - Path=/orders/**

Add rate limiting:

  • Use Redis for managing tokens for rate-limiting logic.
  • Add this to application.yml:
spring:
  cloud:
    gateway:
      routes:
        - id: user_service
          uri: http://localhost:8081
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20
          predicates:
            - Path=/users/**

Step 2: Microservices Development

Each microservice is an independent Spring Boot application.

Example: User Service

Add dependencies in pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

Create a User Entity:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

    // Getters and Setters
}

Implement UserController:

@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserRepository userRepository;

    @GetMapping
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
}

Step 3: Integrate Redis for Rate Limiting

Add Redis dependency to pom.xml in the API Gateway project:

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

Configure Redis in application.yml:

spring:
  redis:
    host: localhost
    port: 6379

Enable rate limiting:

  • Spring Cloud Gateway uses KeyResolver to identify the client (e.g., by IP or user ID).

Example of a KeyResolver:

@Component
public class UserKeyResolver implements KeyResolver {
    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
    }
}

Register the KeyResolver in application.yml:

spring:
  cloud:
    gateway:
      redis-rate-limiter:
        enabled: true
      default-filters:
        - name: RequestRateLimiter
          args:
            key-resolver: "#{@userKeyResolver}"

Testing the System

Start Redis: Make sure Redis is running on your local machine or server:

redis-server

Run Microservices: Start the API Gateway and individual microservices (User Service, Order Service).

Send Requests: Use a tool like Postman to test the system:

  • Send a request to the API Gateway, e.g., http://localhost:8080/users.
  • If you exceed the rate limit, you’ll receive an HTTP 429 Too Many Requests response.

Key Benefits of This Design

  1. Scalability: Each microservice can scale independently based on demand.
  2. Enhanced Security: The API Gateway ensures secure and controlled access to microservices.
  3. Fair Usage: Rate limiting prevents abuse by limiting the number of requests from a single client.
  4. Centralized Management: API Gateway serves as a single entry point for logging, monitoring, and enforcing policies.

Conclusion

By designing a system using microservices, an API Gateway, and rate limiting, you create a scalable, secure, and robust architecture. This approach ensures fair usage and protects backend services from potential overload. With Spring Boot and Spring Cloud Gateway, implementing this system is straightforward and flexible.

🤞 Never miss a story from us, get weekly updates to your inbox!