The goal of the UniqueIDTracker-Service
implementation was to create a REST service capable of processing at least 10,000 requests per second while adhering to the outlined requirements and extensions. Below are the key design decisions and approaches used to meet the functional and non-functional requirements:
-
High Throughput:
- Used Spring Boot, a lightweight and efficient Java framework, to build the service.
- Configured Nginx as a load balancer with a
least_conn
strategy to distribute incoming requests evenly across multiple application instances.
-
Request Handling and Deduplication:
- Redis is used for high-performance request deduplication to ensure unique requests are processed, even in a distributed setup.
- Each request’s uniqueness is validated using Redis’s
setIfAbsent
mechanism.
-
Scheduled Task for Logging:
- Implemented a scheduled task using Spring's
@Scheduled
annotation to log the count of unique requests every minute.
- Implemented a scheduled task using Spring's
-
HTTP POST Requests to External Endpoints:
- When an endpoint is provided in the request, the service sends a POST request to the external endpoint using Spring WebClient.
- Used retry mechanisms for resilience in case of transient failures.
-
Distributed Streaming for Logging:
- Kafka is used to publish the count of unique requests to a topic (
unique-requests
) instead of logging to a file. - Configured Kafka producer properties for performance optimization.
- Kafka is used to publish the count of unique requests to a topic (
Instead of firing an HTTP GET request, a POST request is sent with a custom JSON payload containing:
- Request ID
- Endpoint
- Unique request count in the current minute.
- Redis acts as the shared deduplication store across all application instances.
- Ensured atomicity of operations using Redis’s
setIfAbsent
and TTL-based keys to avoid race conditions.
- Used Kafka for distributed logging of unique request counts. This ensures scalability and supports downstream processing.
- Horizontal scalability achieved using Docker containers orchestrated by
docker-compose
. - Nginx ensures efficient load distribution across multiple application instances.
- Redis and Kafka were chosen for their performance and scalability in distributed environments.
- Controller Layer: Exposes the
/api/UniqueIDTracker/accept
endpoint. - Service Layer: Handles business logic, including deduplication, asynchronous requests, and scheduled tasks.
- Repository Layer: Provides an abstraction over Redis for deduplication.
-
Redis Service:
- Provides
saveIfAbsent
for atomic deduplication. - Periodically clears Redis keys matching a pattern using
SCAN
for efficient cleanup.
- Provides
-
Kafka Service:
- Publishes unique request counts to a Kafka topic.
- Configured for asynchronous message sending to avoid blocking.
-
WebClient:
- Used for non-blocking HTTP POST requests to external endpoints.
- Configured with retry mechanisms to handle transient errors.
-
Scheduled Reporting:
- Every minute, the unique request count is reported to Kafka and the in-memory counter is reset.
-
Endpoints Tested:
- GET /api/uniqueIDTracker/accept: Verified handling of both valid and invalid requests.
- Payloads:
- Valid:
id
andendpoint
query parameters. - Invalid: Missing
id
or invalid data types.
- Valid:
- Response Validation:
- Expected responses:
"ok"
or"failed"
. - Verified response codes (200, 500).
- Expected responses:
-
Scenarios Covered:
- Duplicate
id
requests. - Requests with and without an external
endpoint
.
- Duplicate
-
Test Setup:
- Configured JMeter to send concurrent requests to
/api/UniqueIDTracker/accept
. - Simulated 10,000+ requests per second using thread groups.
- Configured JMeter to send concurrent requests to
-
Performance Metrics:
- Measured average response time and throughput.
- Ensured Redis and Kafka handled high concurrency without bottlenecks.
-
Results:
- Verified that the system maintained consistent performance under load.
- Identified and tuned Nginx and application configurations to handle peak loads.
- Backend:
- Spring Boot
- Redis
- Kafka
- Load Balancer:
- Nginx
- Containerization:
- Docker
- Docker Compose
- Testing:
- Postman for functional testing.
- JMeter for performance testing.
-
Observability:
- Add Prometheus and Grafana for detailed application metrics and monitoring.
-
Resilience:
- Implement circuit breakers (e.g., using Resilience4j) for external endpoint requests.
-
Scalability:
- Move to Kubernetes for orchestration to handle dynamic scaling requirements.
This approach ensures the service is robust, scalable, and capable of handling high loads in a distributed environment.