Skip to content

sametcn99/MicroServiceLearn

Repository files navigation

MicroServiceLearn

MicroServiceLearn is a .NET 10 sample solution for learning microservice architecture through a gateway-first topology. The repository brings together separate auth, product, and log services with YARP-based routing, JWT authentication, Redis-backed query caching, RabbitMQ messaging, and a product creation saga.

The codebase is designed as a practical learning project rather than a minimal demo. It gives you a realistic environment for studying service boundaries, asynchronous communication, cache invalidation, authorization, and local multi-service development in one place.

What This Project Demonstrates

  • Onion Architecture across multiple services
  • CQRS-style command and query separation
  • API Gateway-first routing with centralized auth and rate limiting
  • JWT access token and refresh token lifecycle management
  • Redis caching for product list queries
  • RabbitMQ-based event publishing and consumption
  • Saga orchestration for product creation audit confirmation
  • Docker Compose-based local development
  • Unit, integration, and gateway-level tests

Solution Structure

The repository is organized as a multi-project .NET solution.

  • src/ApiGateway: public entry point, reverse proxy rules, auth enforcement, and centralized API reference surface
  • src/AuthService: registration, login, refresh token rotation, logout, and role-aware authentication flows
  • src/ProductService: product CRUD, CQRS handlers, Redis cache invalidation, and saga state tracking
  • src/LogService: centralized log ingestion, log querying, and audit event handling
  • src/Shared: shared hosting and logging components
  • tests/AuthService.UnitTests: focused auth and validation tests
  • tests/ProductService.UnitTests: product and saga behavior tests
  • tests/MicroServiceLearn.IntegrationTests: end-to-end integration and gateway scenarios

Architecture Overview

Each main service follows a layered structure:

  • *.API: HTTP endpoints and presentation concerns
  • *.Application: commands, queries, validation, orchestration, and use-case logic
  • *.Domain: entities, enums, and domain behavior
  • *.Infrastructure: persistence, messaging, caching, and external integrations

The default local topology is intentionally simple:

  • ApiGateway is the only public HTTP surface
  • AuthService, ProductService, and LogService stay behind the gateway in the Docker network
  • RabbitMQ carries integration events between services
  • Redis accelerates read-heavy product queries
  • SQL Server stores service data independently

Detailed Architecture Diagram

The diagram below shows the main runtime topology, internal service layers, infrastructure dependencies, and the event-driven product creation flow.

flowchart TB
 user[Browser or API Client]
 smoke[Smoke Test Script]
 unit[Unit Tests]
 integration[Integration Tests]

 subgraph public_surface[Public Surface]
  gateway[ApiGateway\nYARP Routing\nJWT Auth\nRate Limiting\nScalar/OpenAPI]
  docs[Central API Docs\n/openapi and /scalar]
 end

 subgraph docker_net[Docker Network: microservicelearn-local]
  direction TB

  subgraph auth_service[AuthService]
   direction TB
   auth_api[API Layer\nControllers and Endpoints]
   auth_app[Application Layer\nLogin Register Refresh Logout\nValidation and Use Cases]
   auth_domain[Domain Layer\nUsers Refresh Tokens Roles]
   auth_infra[Infrastructure Layer\nEF Core Identity JWT Services]
   auth_db[(Auth SQL Database)]
   auth_api --> auth_app --> auth_domain --> auth_infra --> auth_db
  end

  subgraph product_service[ProductService]
   direction TB
   product_api[API Layer\nProduct Endpoints Saga Status]
   product_app[Application Layer\nCQRS Commands Queries\nSaga Orchestration Validation]
   product_domain[Domain Layer\nProducts Aggregates Saga State]
   product_infra[Infrastructure Layer\nEF Core Redis RabbitMQ]
   product_db[(Product SQL Database)]
   redis[(Redis Cache)]
   product_api --> product_app --> product_domain --> product_infra --> product_db
   product_infra <--> redis
  end

  subgraph log_service[LogService]
   direction TB
   log_api[API Layer\nLog Query and Log Entry Endpoints]
   log_app[Application Layer\nCommands Queries Audit Handling]
   log_domain[Domain Layer\nLog Entries Severity Correlation]
   log_infra[Infrastructure Layer\nEF Core RabbitMQ Structured Logging]
   log_db[(Log SQL Database)]
   log_api --> log_app --> log_domain --> log_infra --> log_db
  end

  subgraph messaging[Messaging Backbone]
   rabbit[(RabbitMQ)]
  end
 end

 user -->|All external HTTP traffic| gateway
 smoke -->|Gateway-first validation| gateway
 integration -->|End-to-end scenarios| gateway
 integration -->|Direct service host tests| auth_api
 integration -->|Direct service host tests| product_api
 integration -->|Direct service host tests| log_api
 unit -->|Isolated application and domain tests| auth_app
 unit -->|Isolated application and domain tests| product_app

 gateway -->|Proxy auth routes| auth_api
 gateway -->|Proxy product routes| product_api
 gateway -->|Proxy log routes| log_api
 gateway -->|Expose aggregated docs| docs

 auth_app -->|Issue access token and refresh token| gateway
 gateway -.->|Validate bearer tokens and enforce policies| product_api
 gateway -.->|Validate bearer tokens and enforce policies| log_api

 product_app -->|Create Product command| product_domain
 product_infra -->|Publish ProductCreatedIntegrationEvent| rabbit
 rabbit -->|Consume product created event| log_infra
 log_app -->|Persist audit trail| log_domain
 log_infra -->|Store audit entry| log_db
 log_infra -->|Publish ProductCreationAuditResultIntegrationEvent| rabbit
 rabbit -->|Consume audit result| product_infra
 product_app -->|Complete saga or compensate| product_domain

 product_api -->|Read product list| product_app
 product_app -->|Query cached list first| redis
 product_app -->|Cache miss fallback| product_infra
 product_app -->|Invalidate cache after writes| redis

 auth_infra -. shared JWT settings .- gateway
 auth_infra -. refresh token cookie lifecycle .- user

 classDef edge fill:#f3f3f3,stroke:#555,stroke-width:1px,color:#111;
 classDef data fill:#fff7e6,stroke:#9a6700,stroke-width:1px,color:#111;
 classDef api fill:#e8f1ff,stroke:#1f5fbf,stroke-width:1px,color:#111;
 classDef app fill:#eefbea,stroke:#2b8a3e,stroke-width:1px,color:#111;
 classDef infra fill:#f5ecff,stroke:#7b3fe4,stroke-width:1px,color:#111;

 class user,smoke,unit,integration,docs edge;
 class gateway,auth_api,product_api,log_api api;
 class auth_app,product_app,log_app,auth_domain,product_domain,log_domain app;
 class auth_infra,product_infra,log_infra infra;
 class auth_db,product_db,log_db,redis,rabbit data;
Loading

See the full diagram here

Key Learning Areas

API Gateway-First Topology

The gateway centralizes routing, authorization, rate limiting, and public API discovery. This keeps downstream services private while giving clients a single entry point.

Authentication and Authorization

The auth flow covers registration, login, refresh token rotation, logout, and logout-all behavior. Product write operations require an admin role, while product reads require a valid JWT.

Event-Driven Communication

RabbitMQ is used for log ingestion and product-related integration events. This keeps services loosely coupled while still allowing them to react to important state changes.

Product Creation Saga

The product creation workflow is more than a single database write. It creates a saga record, publishes an integration event, waits for audit confirmation from the log service, and compensates when the audit flow fails or times out.

Caching Strategy

The product list uses Redis to speed up reads. Create, update, and delete flows invalidate the list cache so stale data is not kept after write operations.

Technology Stack

  • .NET 10
  • C#
  • ASP.NET Core
  • YARP Reverse Proxy
  • MediatR
  • FluentValidation
  • Entity Framework Core
  • SQL Server
  • Redis
  • RabbitMQ
  • Serilog
  • Scalar / OpenAPI
  • Docker Compose
  • GitHub Actions

Prerequisites

For the default local workflow, install:

  • Docker Desktop
  • .NET 10 SDK if you want to build or run services outside containers
  • Visual Studio or VS Code if you want to debug locally

Configuration Model

The root .env.example file contains the local environment template. Copy it to .env before starting the stack.

cp .env.example .env

Windows PowerShell:

Copy-Item .env.example .env

Configuration rules used in this repository:

  • values in .env feed the local runtime and Docker Compose setup
  • keys prefixed with DOCKER_ are used for Compose interpolation and container runtime values
  • application settings are mapped into ASP.NET Core configuration via environment variables
  • shell and CI environment variables can override values from .env

Run the Full Stack with Docker

The main local workflow is Docker Compose.

  1. Copy .env.example to .env.
  2. Review JWT, database, and seed user settings if you want custom values.
  3. Start the stack.
docker compose up --build

Detached mode:

docker compose up --build -d

Stop the stack:

docker compose down

Stop and remove volumes:

docker compose down -v

Default Local Endpoints

Public endpoint:

  • ApiGateway: http://localhost:5138

Internal service endpoints inside the Docker network:

  • auth-service: http://auth-service:8080
  • product-service: http://product-service:8080
  • log-service: http://log-service:8080
  • sqlserver: sqlserver:1433
  • redis: redis:6379
  • rabbitmq: rabbitmq:5672

Compose Artifacts

  • docker-compose.yml: main local topology
  • docker-compose.infrastructure.yml: infrastructure-focused overrides
  • docker-compose.dcproj: Visual Studio Docker Compose orchestration project
  • docker-compose.vs.debug.yml: Visual Studio debug override
  • docker-compose.debug.yml: extra debug-oriented compose settings

Database and Startup Behavior

Each service applies its own migrations during startup in the local development workflow. This keeps first-run setup simple and reduces the number of manual steps needed to get the stack running.

API Documentation

The gateway exposes a central API reference surface for the downstream services.

  • Scalar UI: http://localhost:5138/scalar
  • Gateway OpenAPI: http://localhost:5138/openapi/v1.json
  • Auth OpenAPI through gateway: http://localhost:5138/openapi/auth/v1.json
  • Product OpenAPI through gateway: http://localhost:5138/openapi/products/v1.json
  • Log OpenAPI through gateway: http://localhost:5138/openapi/logs/v1.json

Testing

Run the .NET Test Suite

dotnet test MicroServiceLearn.slnx -c Release

Run the Smoke Test Script

After the Docker stack is up, run:

./smoke-test.ps1

The smoke test validates:

  • gateway health and OpenAPI availability
  • auth register, login, refresh, logout, and logout-all flows
  • role-based access rules on product and log endpoints
  • product create, update, delete, and saga status scenarios
  • gateway rate limiting behavior on auth endpoints

Manual checks that are useful while learning the system:

  1. Verify that GET /api/products returns 401 without a token and 200 with a valid token.
  2. Verify that admin credentials can create, update, and delete products.
  3. Verify that the refresh token cookie named microservicelearn_refresh_token is rotated on refresh.
  4. Verify that product creation returns a SagaId and that saga state eventually reaches completion.
  5. Verify that repeated login failures through the gateway eventually trigger 429 Too Many Requests.

Visual Studio Docker Compose Workflow

The solution includes Visual Studio Docker Compose artifacts for local debugging.

Useful profiles in Properties/launchSettings.json:

  • Docker Compose: brings up the full application stack with debugging support
  • Gateway Only: useful when you mainly want to inspect routing, auth, or gateway behavior
  • Infrastructure Only: useful when you want SQL Server, Redis, and RabbitMQ running before starting APIs manually

Typical workflow:

  1. Prepare .env.
  2. Open MicroServiceLearn.slnx in Visual Studio.
  3. Choose the Docker Compose startup target.
  4. Start with Gateway Only for everyday work or Docker Compose for full-stack debugging.

CI

The repository includes a GitHub Actions workflow at .github/workflows/build.yml.

It currently performs:

  • .NET SDK setup
  • solution restore
  • release build
  • test execution
  • test result artifact upload

Suggested Learning Extensions

If you want to continue evolving the project, useful follow-up areas include:

  • distributed tracing and observability
  • richer policy-based authorization rules
  • external identity provider integration
  • stronger retry and process manager patterns
  • production-grade CI/CD and deployment automation
  • more advanced cache key strategies and invalidation policies

Current Limitations

This repository is intentionally focused on local development and architecture learning. A few areas are still simplified:

  • observability is functional but not fully production-oriented
  • CI is build-and-test focused, not full delivery automation
  • saga orchestration is representative, not an exhaustive workflow engine
  • infrastructure is tuned for local understanding rather than cloud deployment hardening

About

learning repo

Topics

Resources

Stars

Watchers

Forks

Contributors