Skip to content

george-marcus/microservices-enterprise

Repository files navigation

Enterprise Microservices Solution

A production-ready .NET Core microservices architecture featuring comprehensive caching, fault tolerance, authentication, and async messaging.

Architecture Overview

Microservices

  • User Service (Port 5001) - User management with CRUD operations
  • Order Service (Port 5002) - Order processing and business logic
  • Notification Service (Port 5003) - Async event-driven notifications
  • Identity Service (Port 5004) - Authentication and authorization (IdentityServer)
  • API Gateway (Port 5000) - YARP reverse proxy with auth integration

Infrastructure Components

  • Redis - Distributed caching layer
  • RabbitMQ - Message bus for async communication
  • SQL Server - Database for Identity Service
  • Jaeger - Distributed tracing
  • Prometheus - Metrics monitoring
  • Docker/Kubernetes - Full containerization and orchestration

Shared Libraries

  • Common - Shared models, interfaces, and utilities
  • Caching - Redis caching abstraction with fallback support
  • EventBus - RabbitMQ integration for event-driven architecture
  • Saga - Orchestration-based saga pattern for distributed transactions
  • Outbox - Transactional outbox pattern for reliable event publishing

Key Features

1. Distributed Caching (Redis)

  • Cache-aside pattern with automatic fallback
  • TTL-based expiration (configurable per service)
  • Cache invalidation on data mutations
  • GetOrSet pattern for efficient cache population

Example usage in UserServiceImpl.cs:

var cachedUser = await _cache.GetAsync<User>(cacheKey);
if (cachedUser != null) return ApiResponse<User>.SuccessResponse(cachedUser);

2. Fault Tolerance (Polly 8.x)

All four resilience patterns implemented for HTTP inter-service communication:

Circuit Breaker

  • Opens after 50% failure rate (5 min requests)
  • Breaks for 30 seconds
  • Prevents cascading failures

Retry with Exponential Backoff

  • 3 retry attempts with jitter
  • Exponential delay: ~2s, ~4s, ~8s
  • Handles transient failures

Timeout

  • 10s per attempt timeout
  • 30s total request timeout
  • Prevents resource exhaustion

Bulkhead Isolation (Rate Limiter)

  • Max 10 concurrent requests
  • Queue limit: 5 requests
  • Prevents thread pool exhaustion

See POLLY-RESILIENCE.md for configuration details.

3. Authentication (Identity Service)

  • OAuth 2.0 / OpenID Connect via IdentityServer
  • Client credentials flow for service-to-service auth
  • JWT token validation across all services
  • Centralized identity management

4. Inter-Service Communication

The solution implements both synchronous and asynchronous communication patterns:

Synchronous (HTTP with Polly Resilience)

  • UserService → OrderService: Fetch user's orders for profile aggregation
  • OrderService → UserService: Validate user exists before creating order

Features:

  • Named HttpClient with connection pooling
  • All 4 Polly resilience patterns applied
  • Graceful degradation on service unavailability
  • Comprehensive error handling and logging

See HTTPCLIENT-USAGE.md for implementation details.

Asynchronous (RabbitMQ Event Bus)

  • UserCreatedEvent: User registration notifications
  • OrderCreatedEvent: Order placement notifications
  • OrderStatusChangedEvent: Order status updates

Event Flow:

UserService → UserCreatedEvent → NotificationService
OrderService → OrderCreatedEvent → NotificationService
OrderService → OrderStatusChangedEvent → NotificationService

5. Saga Pattern with Outbox

  • Orchestration-based sagas for distributed transactions
  • Compensating transactions for automatic rollback
  • Transactional outbox for guaranteed event delivery
  • At-least-once delivery semantics
  • Idempotency support for exactly-once processing (cache or database-based)

OrderSaga Flow:

1. CreateOrder → 2. ProcessPayment → 3. ReserveInventory → 4. SendNotification
                    ↓ Failure                ↓ Compensation
              Refund ← Delete Order ← Release Inventory

Idempotency:

  • Each event has unique idempotency key
  • Prevents duplicate processing on retries
  • Choice of Redis (fast) or database (durable) storage

See SAGA-PATTERN.md and IDEMPOTENCY-GUIDE.md for detailed documentation.

6. API Gateway (YARP)

  • Single entry point for all services
  • Reverse proxy routing to backend services
  • Authentication integration with Identity Service
  • Load balancing support

Project Structure

EnterpriseMicroservices/
├── src/
│   ├── BuildingBlocks/
│   │   ├── Common/              # Shared models and interfaces
│   │   ├── Caching/             # Redis caching abstraction
│   │   ├── EventBus/            # RabbitMQ integration
│   │   ├── Saga/                # Saga orchestration pattern
│   │   └── Outbox/              # Transactional outbox pattern
│   ├── Services/
│   │   ├── UserService/         # User management service
│   │   ├── OrderService/        # Order processing with saga
│   │   ├── NotificationService/ # Notification service
│   │   └── IdentityService/     # Authentication (IdentityServer)
│   └── Gateway/                 # API Gateway (YARP)
├── k8s/                         # Kubernetes deployment
│   ├── base/                    # Base Kustomize configurations
│   │   ├── services/            # Service deployments
│   │   ├── infrastructure/      # Redis, RabbitMQ, SQL, Jaeger, Prometheus
│   │   ├── hpa/                 # Horizontal Pod Autoscalers
│   │   └── network-policies/    # Zero-trust network security
│   └── overlays/                # Environment-specific overrides
│       ├── development/
│       └── production/
├── Docs/                        # Documentation
├── docker-compose.yml           # Docker orchestration
└── EnterpriseMicroservices.sln  # Solution file

Getting Started

Prerequisites

  • .NET 10.0 SDK
  • Docker Desktop
  • (Optional) Visual Studio 2025 or VS Code

Running with Docker (Recommended)

  1. Build and start all services:

    docker-compose up --build
  2. Access the services:

  3. Stop all services:

    docker-compose down

Running on Kubernetes

Prerequisites:

  • Kubernetes cluster (minikube, kind, Docker Desktop, or cloud)
  • Metrics Server (required for HPA)
  • CNI with NetworkPolicy support (Calico, Cilium, Weave Net)
# Development deployment
kubectl apply -k k8s/overlays/development

# Production deployment
kubectl apply -k k8s/overlays/production

# Watch pods
kubectl get pods -n microservices -w

# View HPA status
kubectl get hpa -n microservices

# Access via port-forward
kubectl port-forward svc/apigateway 5000:5000 -n microservices

See Docs/kubernetes-deployment.md for detailed K8s deployment guide.

Running Locally (Development)

  1. Start infrastructure services:

    docker-compose up redis rabbitmq sqlserver
  2. Run each service:

    # Terminal 1 - Identity Service (start first)
    cd src/Services/IdentityService
    dotnet run
    
    # Terminal 2 - User Service
    cd src/Services/UserService
    dotnet run
    
    # Terminal 3 - Order Service
    cd src/Services/OrderService
    dotnet run
    
    # Terminal 4 - Notification Service
    cd src/Services/NotificationService
    dotnet run
    
    # Terminal 5 - API Gateway
    cd src/Gateway
    dotnet run

API Endpoints

Via API Gateway (http://localhost:5000)

Users

  • GET /api/users - Get all users
  • GET /api/users/{id} - Get user by ID
  • GET /api/users/{id}/with-orders - Get user with orders (inter-service call)
  • POST /api/users - Create new user
  • PUT /api/users/{id} - Update user
  • DELETE /api/users/{id} - Delete user

Orders

  • GET /api/orders - Get all orders
  • GET /api/orders/{id} - Get order by ID
  • GET /api/orders/user/{userId} - Get orders by user ID
  • POST /api/orders - Create new order
  • PATCH /api/orders/{id}/status - Update order status
  • DELETE /api/orders/{id} - Cancel order

Order Saga (Distributed Transactions)

  • POST /api/ordersaga - Create order with saga pattern
    • Executes: CreateOrder → ProcessPayment → ReserveInventory → SendNotification
    • Auto-compensation on failure

Testing the Solution

1. Create a User

curl -X POST http://localhost:5000/api/users \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "John",
    "lastName": "Doe",
    "email": "john.doe@example.com",
    "department": "Engineering",
    "role": "Developer"
  }'

2. Create an Order

curl -X POST http://localhost:5000/api/orders \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "{user-id-from-step-1}",
    "items": [
      {
        "productName": "Laptop",
        "quantity": 1,
        "unitPrice": 1200.00
      }
    ]
  }'

3. Update Order Status

curl -X PATCH http://localhost:5000/api/orders/{order-id}/status \
  -H "Content-Type: application/json" \
  -d '"Confirmed"'

4. Check Notifications

Check the NotificationService logs to see event processing:

docker logs notificationservice

5. Test Saga Pattern (Distributed Transaction)

curl -X POST http://localhost:5002/api/ordersaga \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "{user-id-from-step-1}",
    "totalAmount": 1500.00
  }'

Expected Flow:

  1. Order created in database
  2. Payment processed
  3. Inventory reserved
  4. Notification event saved to outbox
  5. Background processor publishes event
  6. Notification sent

If any step fails, compensation runs automatically:

  • Refunds payment
  • Releases inventory
  • Deletes order

See SAGA-PATTERN.md for detailed testing scenarios.

Configuration

Redis Configuration

Edit appsettings.json in each service:

{
  "ConnectionStrings": {
    "Redis": "localhost:6379"
  },
  "Redis": {
    "InstanceName": "ServiceName_"
  }
}

RabbitMQ Configuration

{
  "RabbitMQ": {
    "Host": "localhost"
  }
}

Authentication Configuration

{
  "Authentication": {
    "Authority": "http://localhost:5004"
  },
  "ClientCredentials": {
    "Authority": "http://localhost:5004",
    "ClientId": "service-client",
    "ClientSecret": "your-secret"
  }
}

Polly Resilience Configuration

Customize in PollyPolicies.cs:

  • Retry count and delay
  • Circuit breaker thresholds
  • Timeout duration
  • Bulkhead limits

Monitoring and Health Checks

Health Check Endpoints

RabbitMQ Management

Monitor queues and messages: http://localhost:15672

Distributed Tracing (Kubernetes)

Access Jaeger UI: kubectl port-forward svc/jaeger 16686:16686 -n microservices

Metrics (Kubernetes)

Access Prometheus: kubectl port-forward svc/prometheus 9090:9090 -n microservices

Technology Stack

  • .NET 10.0 - Latest .NET runtime
  • ASP.NET Core - Web API framework
  • Entity Framework Core - ORM with SQL Server
  • IdentityServer (Duende) - Authentication/Authorization
  • Redis - Distributed caching
  • RabbitMQ - Message broker
  • YARP - API Gateway (reverse proxy)
  • Polly - Resilience and fault tolerance
  • Docker - Containerization
  • Kubernetes - Container orchestration
  • Jaeger - Distributed tracing
  • Prometheus - Metrics monitoring
  • OpenTelemetry - Observability

Best Practices Implemented

  1. Separation of Concerns - Clear boundaries between services
  2. DRY Principle - Shared libraries for common functionality
  3. Fail-Fast - Circuit breakers prevent cascading failures
  4. Cache-Aside Pattern - Efficient caching with Redis
  5. Event-Driven Architecture - Loose coupling via message bus
  6. Health Checks - Monitoring and automatic recovery
  7. Zero-Trust Security - NetworkPolicies for network segmentation
  8. Container-First - Full Docker and Kubernetes support

Scaling Considerations

Horizontal Scaling

Docker Compose:

docker-compose up --scale userservice=3 --scale orderservice=2

Kubernetes (Automatic with HPA):

kubectl get hpa -n microservices
Service Min Replicas Max Replicas CPU Target
API Gateway 2 10 70%
User Service 2 8 70%
Order Service 2 8 70%
Notification Service 2 6 70%
Identity Service 2 6 70%

Load Balancing

  • Kubernetes: K8s Services provide built-in load balancing
  • Docker: Docker Compose DNS-based service discovery

Network Security (Kubernetes)

Zero-trust NetworkPolicies control all pod-to-pod communication:

  • Default deny all traffic
  • Explicit allow rules for each service
  • Infrastructure isolation (only specific services can access databases)

Cache Considerations

  • Redis shared across all instances
  • Cache invalidation coordinated via cache keys

Troubleshooting

Service won't start

  1. Check Docker containers: docker ps -a
  2. View service logs: docker logs <container-name>
  3. Verify infrastructure health: RabbitMQ Management UI

Cache not working

  1. Verify Redis connection: docker logs redis
  2. Check connection string in appsettings.json
  3. Test Redis: docker exec -it redis redis-cli ping

Events not processing

  1. Check RabbitMQ: http://localhost:15672
  2. Verify NotificationService is running
  3. Check event handler registration in Program.cs

Authentication issues

  1. Verify Identity Service is running: http://localhost:5004/.well-known/openid-configuration
  2. Check client credentials in appsettings.json
  3. Ensure JWT tokens are being passed in Authorization header

Future Enhancements

  • Add API versioning
  • Implement CQRS pattern
  • Add centralized logging (Elasticsearch, Seq)
  • Implement rate limiting at gateway level
  • Add Pod Disruption Budgets for HA
  • Implement Redis Sentinel/Cluster for HA
  • Add RabbitMQ clustering

License

This project is provided as-is for educational and development purposes.

Contributing

Feel free to submit issues and enhancement requests.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors