Knowledge

Dapr para microsserviços: padrões de produção sem reinventar a roda

Como o Distributed Application Runtime simplifica desafios comuns de microsserviços como state management, pub/sub e service invocation.

11/03/20267 min de leituraKnowledge
Dapr para microsserviços: padrões de produção sem reinventar a roda

Resumo executivo

Como o Distributed Application Runtime simplifica desafios comuns de microsserviços como state management, pub/sub e service invocation.

Ultima atualizacao: 11/03/2026

O problema da arquitetura de microsserviços

Quando equipes migram de monolitos para microsserviços, rapidamente descobrem que distribuir um sistema introduz uma nova categoria de problemas que não existiam antes. Cada serviço precisa lidar com comunicação entre serviços, gerenciamento de estado, mensageria, resiliência, observabilidade e uma dúzia de outros desafios transversais.

A resposta tradicional? Cada time reinventa a roda. O time de payments constrói seu próprio abstração de Redis. O time de orders implementa seu cliente Kafka. O time de notifications desenvolve sua estratégia de retry. Três anos depois, você tem 15 implementações diferentes dos mesmos padrões fundamentais, cada uma com bugs, edge cases e documentação incompleta.

Dapr (Distributed Application Runtime) resolve isso fornecendo building blocks padronizados que você simplesmente usa—sem precisar construir.

O que é Dapr e como funciona

Dapr é um runtime de código aberto que facilita o desenvolvimento de aplicações distribuídas. Ele usa o padrão sidecar: um container Dapr roda ao lado de seu container de aplicação, expondo APIs HTTP e gRPC que sua aplicação consome.

Arquitetura sidecar

┌─────────────────────────────────────────┐
│           Pod Kubernetes             │
│  ┌──────────────────────────────┐   │
│  │   Your Application           │   │
│  │   (language agnostic)        │   │
│  │                             │   │
│  │   HTTP/gRPC to localhost    │   │
│  │   :3500, :50001            │   │
│  └──────────────────────────────┘   │
│              ↕                      │
│  ┌──────────────────────────────┐   │
│  │   Dapr Sidecar              │   │
│  │   (distributed primitives)  │   │
│  └──────────────────────────────┘   │
└─────────────────────────────────────────┘

Benefícios fundamentais:

  • Agnóstico de linguagem: Qualquer linguagem que faça HTTP/gRPC funciona
  • Independente de plataforma: Kubernetes, VMs, edge, development machines
  • Building blocks reutilizáveis: State, pub/sub, bindings, actors, e mais

Building Blocks do Dapr

Service Invocation

Invocação de serviço simplificada com auto-discovery, retry, mTLS e observabilidade.

go// Go: chamar serviço usando Dapr
req := &dapr.InvokeMethodRequest{
  Method: "GET",
  ContentType: "application/json",
  QueryString: "?id=123",
}

response, err := daprClient.InvokeMethod(
  ctx,
  "orders-service",
  "api/orders/123",
  req,
)

Comparação com HTTP direto:

AspectoHTTP diretoDapr Service Invocation
Service discoveryManual (DNS, SRV)Automático
Load balancingExternal (Ingress)Embutido
Retry logicManualConfigurável
mTLSManual implementaçãoAutomático
ObservabilityMiddleware customEmbutido

State Management

Armazenamento de estado abstraído—troque Redis por DynamoDB sem mudar código.

python# Python: salvar estado
state = {
  "orderId": 123,
  "status": "pending",
  "items": ["item1", "item2"]
}

dapr.save_state(
  store_name="orders-store",
  key=f"order-{order_id}",
  value=state
)

# Ler estado
order = dapr.get_state(
  store_name="orders-store",
  key=f"order-{order_id}"
)

Operações suportadas:

  • Get, Delete, Bulk Get, Bulk Delete
  • E-tags para controle de concorrência
  • Transactions atômicas (multi-key)
  • State stores: Redis, PostgreSQL, DynamoDB, Azure Cosmos DB, GCP Firestore

Publish-Subscribe

Pub/sub desacoplado com suporte a at-least-once delivery.

typescript// TypeScript: publicar evento
await dapr.publish(
  'order-events',
  'OrderCreated',
  {
    orderId: 123,
    customerId: 456,
    timestamp: new Date().toISOString()
  }
)
yaml# subscription.yaml - declarar subscription
apiVersion: dapr.io/v1alpha1
kind: Subscription
metadata:
  name: order-created-sub
spec:
  topic: order-events
  route: /events/order-created
  pubsubname: orders-pubsub
scopes:
- payment-service
- inventory-service

Características:

  • Dead-letter queues automáticas
  • Routing baseado em conteúdo
  • At-least-once delivery com deduplication
  • Menssageiros: Kafka, RabbitMQ, AWS SQS, Azure Service Bus, GCP Pub/Sub

Bindings

Integrações com sistemas externos sem escrever código específico.

yaml# binding.yaml - binding para AWS S3
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: s3-binding
spec:
  type: bindings.aws.s3
  version: v1
  metadata:
  - name: bucket
    value: "my-bucket"
  - name: region
    value: "us-east-1"
  - name: accessKey
    value: "${AWS_ACCESS_KEY_ID}"
  - name: secretKey
    value: "${AWS_SECRET_ACCESS_KEY}"
go// Enviar arquivo para S3
file, _ := os.Open("report.pdf")
in := &dapr.InvokeBindingRequest{
  Name: "s3-binding",
  Data: file,
  Operation: "create",
}
client.InvokeBinding(context.Background(), in)

Bindings disponíveis:

  • Cloud: AWS (S3, SNS, SQS, DynamoDB), Azure (Blob, Event Grid), GCP (Pub/Sub, Storage)
  • Databases: PostgreSQL, MySQL, MongoDB, Redis
  • Outros: HTTP, Cron, Kafka, RabbitMQ

Actors

Modelo de ator com concorrência e lifecycle management.

java// Java: definir ator
@ActorType(name = "OrderProcessor")
public class OrderProcessorActor {
  private ActorRuntimeContext context;

  @Override
  public void activate(ActorRuntimeContext ctx) {
    this.context = ctx;
  }

  @ActorMethod(name = "ProcessOrder")
  public CompletableFuture<String> processOrder(Order order) {
    // Processamento serial para cada orderId
    // Dapr garante exatamente uma instância por ator
    return CompletableFuture.completedFuture("Order processed");
  }
}

Características de atores:

  • Concurrencia por chave (nível de ator)
  • Timers e reminders automáticos
  • Persistence automática
  • Virtual actors (escala ilimitada)

Deployment em produção

Habilitando Dapr sidecar injection

bash# Instalar Dapr no cluster
helm repo add dapr https://dapr.github.io/helm-charts/
helm repo update
helm install dapr dapr/dapr --namespace dapr-system

# Habilitar injeção em namespace
kubectl label namespace production dapr.io/enabled=true
yaml# deployment.yaml - anotações para injeção
apiVersion: apps/v1
kind: Deployment
metadata:
  name: orders-service
spec:
  template:
    metadata:
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "orders-service"
        dapr.io/app-port: "3000"
        dapr.io/config: "production"

Configuração de production

yaml# config.yaml - configuração Dapr de produção
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: production
spec:
  tracing:
    samplingRate: "0.1"  # 10% sampling
    zipkin:
      endpointAddress: "http://jaeger-collector:9411/api/v2/spans"
  metrics:
    enabled: true
    http:
      port: 9090
  secrets:
    scopes:
      - storeName: "kubernetes"  # Segredos do K8s

Componentes de state store para produção

yaml# statestore.yaml - Redis com persistência
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: orders-store
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: "redis-master:6379"
  - name: redisPassword
    secretKeyRef:
      name: redis-secrets
      key: password
  - name: enableTLS
    value: "true"
  - name: clientCert
    secretKeyRef:
      name: redis-secrets
      key: client-cert
  - name: clientKey
    secretKeyRef:
      name: redis-secrets
      key: client-key

Padrões de arquitetura com Dapr

Padrão 1: Saga pattern com Dapr Actors

Implemente sagas distribuídas usando atores para gerenciar compensação.

typescript// Orchestration Actor
class OrderSagaActor {
  async start(orderId: string) {
    const order = await this.state.get<Order>(`order:${orderId}`);
    await this.compensateIfFailed(order);

    // Passo 1: Reservar estoque
    await actorProxy.execute('InventoryActor', order.id, 'Reserve');

    // Passo 2: Processar pagamento
    const paymentResult = await actorProxy.execute(
      'PaymentActor',
      order.id,
      'Charge'
    );

    if (!paymentResult.success) {
      await this.compensate(order);
      return { status: 'failed', reason: 'payment_failed' };
    }

    // Passo 3: Confirmar estoque
    await actorProxy.execute('InventoryActor', order.id, 'Confirm');

    return { status: 'completed' };
  }

  async compensate(order: Order) {
    await actorProxy.execute('InventoryActor', order.id, 'Release');
  }
}

Padrão 2: Event sourcing com Dapr State

Use Dapr para armazenar eventos e reconstruir estado.

python# Armazenar eventos
for event in order_events:
    dapr.save_state(
        store_name="events-store",
        key=f"event-{event.id}",
        value={
            "id": event.id,
            "orderId": event.order_id,
            "type": event.type,
            "data": event.data,
            "timestamp": event.timestamp,
            "__etag": str(event.version)
        }
    )

# Reconstruir estado agregado
events = dapr.get_state(store_name="events-store", key=f"order-{order_id}")
order_state = aggregate_events(events)

Padrão 3: CQRS com Dapr bindings

Separar command handling de query handling usando bindings.

yaml# Commands: Pub/Sub
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: commands-pubsub
spec:
  type: pubsub.redis
  version: v1

# Queries: Database binding
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: queries-db
spec:
  type: bindings.postgres
  version: v1
go// Command handler
func handleCommand(event CommandEvent) {
  dapr.publish("commands-pubsub", event.Type, event.Data)
}

// Query handler
func handleQuery(query Query) {
  result := dapr.invokeBinding("queries-db", "query", query)
  return result
}

Considerações de production

Performance e scaling

yaml# Configuração de recursos para sidecar
apiVersion: apps/v1
kind: Deployment
metadata:
  name: orders-service
spec:
  template:
    metadata:
      annotations:
        dapr.io/enabled: "true"
        dapr.io/sidecar-cpu-limit: "500m"
        dapr.io/sidecar-memory-limit: "512Mi"
        dapr.io/sidecar-cpu-request: "100m"
        dapr.io/sidecar-memory-request: "128Mi"

Resiliência e retry

yaml# configuration.yaml - retry policy
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: production
spec:
  appHttpPipeline:
    handlers:
    - name: retry-policy
      type: middleware.http.retry
      spec:
        maxRetries: 3
        backoffPolicy: exponential
        exponentialBackoff:
          initialInterval: 500ms
          randomizationFactor: 0.5
          multiplier: 1.5
          maxInterval: 30s

Segurança e mTLS

yaml# Ativar mTLS entre serviços
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: production
spec:
  mtls:
    enabled: true
    workloadCertTTL: "24h"
    allowedClockSkew: "15m"

Quando Dapr é excessivo

Dapr resolve muitos problemas, mas não é a resposta para tudo.

Dapr não é ideal quando:

  • Seu sistema tem poucos serviços (2-3)
  • Comunicação é 1:1 sem topologias complexas
  • Você já tem soluções consolidadas que funcionam bem

Dapr é ideal quando:

  • Você tem 10+ serviços comunicando-se
  • Múltiplas linguagens/frameworks no stack
  • Precisa de consistência em patterns distribuídos
  • Time-to-market é mais importante que controle total da infraestrutura

Conclusão

Dapr transforma a arquitetura de microsserviços de um problema complexo e repetitivo em uma composição de building blocks testados. Em vez de cada time reconstruir o mesmo código de pub/sub, state management e resiliência, você foca na lógica de negócio única que agrega valor.

O sidecar pattern permite que qualquer linguagem participe de uma arquitetura cloud-native consistente. Sua equipe de Go, Java e Python todos usam os mesmos building blocks, com as mesmas garantias de produção.

Comece com Dapr em um serviço não-crítico, valide que os building blocks atendem suas necessidades, e expanda gradualmente. Em meses, você terá eliminado código boilerplate de milhares de linhas e consolidado padrões distribuídos que antes estavam espalhados por toda sua organização.


Planejando uma arquitetura de microsserviços ou modernizando legado? Fale com especialistas em cloud-native da Imperialis para projetar uma estratégia Dapr que acelere desenvolvimento e reduza complexidade.

Fontes

Leituras relacionadas