DEV Community

Cover image for Criando uma Base Microservices com .NET
Danilo O. Pinheiro, dopme.io
Danilo O. Pinheiro, dopme.io

Posted on

Criando uma Base Microservices com .NET

Com a crescente demanda por escalabilidade, modularidade e entregas contínuas, arquiteturas baseadas em microserviços tornaram-se padrão em aplicações modernas.

Neste artigo, vamos construir uma base sólida para aplicações distribuídas usando .NET 6/7/8, com foco em boas práticas de arquitetura, comunicação entre serviços, mensageria, escalabilidade e observabilidade.


🚀 O que Vamos Construir

Uma arquitetura básica com os seguintes serviços:

Serviço Função
Gateway API Gateway com Ocelot
Catalog Service Catálogo de produtos
Order Service Processamento de pedidos
Message Broker Comunicação assíncrona (RabbitMQ)
Shared Library Contratos, DTOs e eventos comuns
Observability Logs, métricas e tracing

🧰 Tecnologias Utilizadas

Tecnologia Descrição
.NET 8 Backend moderno com ASP.NET Web API
Docker Containerização e orquestração local
Ocelot API Gateway leve para .NET
RabbitMQ Mensageria assíncrona entre microserviços
Dapper/EF Core Acesso a dados simples e performático
MongoDB / SQL Persistência dos serviços
Serilog Logging estruturado
OpenTelemetry Observabilidade e tracing distribuído
Jaeger/Grafana Visualização de traces e métricas

🧱 Estrutura Inicial

/src
 ├── Gateway
 ├── Services
 │   ├── CatalogService
 │   └── OrderService
 ├── BuildingBlocks
 │   ├── EventBus
 │   └── SharedKernel
/docker
 ├── docker-compose.yml
Enter fullscreen mode Exit fullscreen mode

🛠️ Setup do Projeto

1. Criando o Gateway (Ocelot)

dotnet new web -n Gateway
cd Gateway
dotnet add package Ocelot
Enter fullscreen mode Exit fullscreen mode

ocelot.json:

{
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/catalog/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [{ "Host": "catalogservice", "Port": 5001 }],
      "UpstreamPathTemplate": "/catalog/{everything}",
      "UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE" ]
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "http://localhost:5000"
  }
}
Enter fullscreen mode Exit fullscreen mode

2. Criando o Catalog Service

dotnet new webapi -n CatalogService
Enter fullscreen mode Exit fullscreen mode

Controller de exemplo:

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    [HttpGet]
    public IActionResult GetAll() => Ok(new[] {
        new { Id = 1, Name = "Produto A" },
        new { Id = 2, Name = "Produto B" }
    });
}
Enter fullscreen mode Exit fullscreen mode

3. Order Service com Consumo de Mensagem

dotnet new webapi -n OrderService
dotnet add package RabbitMQ.Client
Enter fullscreen mode Exit fullscreen mode

Consumidor de evento (simples):

var factory = new ConnectionFactory() { HostName = "rabbitmq" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();

channel.QueueDeclare("order-queue", false, false, false, null);
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) => {
    var body = ea.Body.ToArray();
    var message = Encoding.UTF8.GetString(body);
    Console.WriteLine($"Pedido recebido: {message}");
};

channel.BasicConsume(queue: "order-queue", autoAck: true, consumer: consumer);
Enter fullscreen mode Exit fullscreen mode

📦 Comunicação Assíncrona com RabbitMQ

Publicador no CatalogService:

var factory = new ConnectionFactory() { HostName = "rabbitmq" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
channel.QueueDeclare("order-queue", false, false, false, null);

string message = JsonSerializer.Serialize(new { OrderId = Guid.NewGuid() });
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish("", "order-queue", null, body);
Enter fullscreen mode Exit fullscreen mode

🐳 Docker Compose

version: '3.8'
services:
  gateway:
    build: ./Gateway
    ports:
      - "5000:80"
    depends_on:
      - catalogservice
      - orderservice

  catalogservice:
    build: ./Services/CatalogService
    ports:
      - "5001:80"

  orderservice:
    build: ./Services/OrderService
    ports:
      - "5002:80"

  rabbitmq:
    image: rabbitmq:3-management
    ports:
      - "5672:5672"
      - "15672:15672"
Enter fullscreen mode Exit fullscreen mode

🔍 Observabilidade com OpenTelemetry

Instale:

dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Exporter.Jaeger
Enter fullscreen mode Exit fullscreen mode

Configure em Program.cs:

builder.Services.AddOpenTelemetry()
    .WithTracing(b => b
        .AddAspNetCoreInstrumentation()
        .AddHttpClientInstrumentation()
        .AddJaegerExporter(opt => {
            opt.AgentHost = "jaeger";
            opt.AgentPort = 6831;
        }));
Enter fullscreen mode Exit fullscreen mode

🔁 Estratégias Futuras

  • 🔐 Autenticação com IdentityServer ou JWT
  • 🌍 Service Discovery com Consul/Eureka
  • 🧪 Contratos assíncronos com Pact.io
  • 📦 Event Sourcing / CQRS com MediatR
  • 🌐 gRPC entre serviços de alta performance

✅ Conclusão

Ter uma base sólida para microserviços com .NET é essencial para construir sistemas modernos, escaláveis e resilientes. Comece simples, usando padrões como mensageria, API Gateway e observabilidade, e evolua conforme as necessidades reais da sua aplicação.


🔗 Recursos Úteis


🤝 Conecte-se Comigo

Fique à vontade para conversar sobre arquitetura, migração e modernização de aplicações .NET:

Disse-lhe o jovem: Tudo isso tenho guardado desde a minha mocidade; que me falta ainda?

Mateus 19:20

Top comments (0)