This project is a deep-dive into Distributed Systems Architecture. It demonstrates a resilient, scalable, and secure backend ecosystem built using the Spring Cloud stack. Rather than a simple monolithic application, this project focuses on solving the complexities of inter-service communication, fault tolerance, and observability.
The system follows a Database-per-Service pattern to ensure loose coupling and independent scalability.
Acting as the "Digital Phonebook" of the system. Every service registers as a @EurekaClient, allowing them to discover each other dynamically without hardcoded IP addresses or ports.
The Spring Cloud Gateway handles all incoming traffic. It provides:
- Dynamic Routing: Directing requests to appropriate services based on path predicates.
- Client-Side Load Balancing: Automatically distributing traffic across multiple instances of a service.
The system is secured at the edge.
- OAuth 2.0 / JWT: The Gateway acts as an OAuth2 Resource Server, validating JWT tokens issued by Keycloak before forwarding requests.
- Centralized Auth: Eliminates the need to implement security logic in every individual service.
I implemented Resilience4j to prevent cascading failures. The Order Service uses a Circuit Breaker when communicating with the Inventory Service.
- 🟢 Closed: Normal state; requests flow through.
- 🔴 Open: If the error rate exceeds the threshold, the circuit trips, failing fast to save system resources.
- 🟡 Half-Open: The system cautiously checks if the downstream service has recovered.
- Fallback Methods: Returns a "Service is temporarily unavailable" message instead of a generic 500 error.
To decouple services, I utilized Apache Kafka.
- Producer: The
Order Servicepublishes anOrderPlacedEventto a Kafka topic once an order is validated. - Consumer: The
Notification Servicelistens to this topic and processes notifications asynchronously, ensuring the main user flow is never blocked.
Debugging distributed systems requires visibility.
- Micrometer Tracing: The successor to Spring Cloud Sleuth, it generates unique
Trace IDsandSpan IDsfor every request. - Zipkin: All traces are exported to Zipkin, providing a visual timeline of a request as it travels across multiple services.
| Module | Purpose | Port | Database |
|---|---|---|---|
discovery-server |
Service Registry | 8761 | - |
api-gateway |
Routing & Security | 8080 | - |
product-service |
Catalog Mgmt | 8081 | MongoDB |
order-service |
Orders & Kafka Producer | 8082 | MySQL |
inventory-service |
Stock Verification | 8083 | MySQL |
notification-service |
Kafka Consumer | 8084 | - |