EngineeringSenior DeveloperArchitecture and Patterns

04 - Microservices Architecture Blueprint

Mỗi service là một ứng dụng ĐỘC LẬP: riêng database, riêng deployment, riêng team. Phức tạp nhất nhưng scale tốt nhất.


Tổng Quan


Khi Nào Dùng / Không Dùng

✅ Dùng khi❌ Không dùng khi
Team > 15 devs, nhiều squadsTeam < 10, single squad
Services cần scale ĐỘC LẬP (order vs search)Mọi thứ scale cùng mức
Cần deploy RIÊNG BIỆT (hotfix 1 service)Deploy cycle chung OK
Technology diversity cần thiếtToàn bộ dùng .NET
Đã có DevOps/SRE teamKhông có infra automation

Dự án hay dùng: Large-scale eCommerce (Shopee, Lazada), Banking core, Ride-hailing, Streaming platforms.


Project Structure (Per Service)

order-service/
├── src/
│   ├── OrderService.Domain/
│   ├── OrderService.Application/
│   ├── OrderService.Infrastructure/
│   └── OrderService.API/
│       ├── Program.cs
│       ├── Dockerfile
│       └── appsettings.json
├── tests/
│   ├── OrderService.UnitTests/
│   └── OrderService.IntegrationTests/
├── order-service.sln
└── .github/workflows/
    └── ci-cd.yml          ← Riêng pipeline cho service này
solution-root/                 ← Tổng thể (optional monorepo)
├── services/
│   ├── order-service/
│   ├── inventory-service/
│   ├── payment-service/
│   └── notification-service/
├── shared/
│   └── Contracts/             ← Shared NuGet package (Integration Events)
├── infra/
│   ├── docker-compose.yml
│   ├── k8s/
│   └── bicep/
└── gateway/
    └── ApiGateway/

Communication Patterns

PatternWhenTech
RESTPublic API, CRUDASP.NET Minimal API
gRPCInternal service-to-service, high throughputGrpc.AspNetCore
Events (async)Fire-and-forget, eventual consistency OKMassTransit + Azure Service Bus
Request/Reply (async)Needs response but can waitMassTransit Request Client

NuGet Essentials (Per Service)

xml
<!-- Communication -->
<PackageReference Include="MassTransit.Azure.ServiceBus.Core" Version="8.*" />
<PackageReference Include="Grpc.AspNetCore" Version="2.*" />

<!-- Resilience -->
<PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="9.*" />

<!-- Observability -->
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.*" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.*" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.*" />

<!-- Infrastructure -->
<PackageReference Include="Azure.Identity" Version="1.*" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.*" />

<!-- Containerization -->
<PackageReference Include="Microsoft.NET.Build.Containers" Version="9.*" />

Docker & Deployment

dockerfile
# Multi-stage build
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY ["OrderService.API/OrderService.API.csproj", "OrderService.API/"]
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app

FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
WORKDIR /app
COPY --from=build /app .
EXPOSE 8080
ENTRYPOINT ["dotnet", "OrderService.API.dll"]
yaml
# docker-compose.yml (Local Development)
services:
  order-service:
    build: ./services/order-service
    ports: ["5001:8080"]
    environment:
      - ConnectionStrings__Default=Server=sqlserver;Database=Orders;...
  inventory-service:
    build: ./services/inventory-service
    ports: ["5002:8080"]
  sqlserver:
    image: mcr.microsoft.com/mssql/server:2022-latest
  redis:
    image: redis:7-alpine
  rabbitmq:
    image: rabbitmq:3-management
    ports: ["15672:15672"]