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.
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:
| Aspecto | HTTP direto | Dapr Service Invocation |
|---|---|---|
| Service discovery | Manual (DNS, SRV) | Automático |
| Load balancing | External (Ingress) | Embutido |
| Retry logic | Manual | Configurável |
| mTLS | Manual implementação | Automático |
| Observability | Middleware custom | Embutido |
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-serviceCaracterí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=trueyaml# 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 K8sComponentes 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-keyPadrõ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: v1go// 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: 30sSeguranç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
- Dapr Documentation — Documentação oficial
- Dapr GitHub Repository — Código-fonte e issues
- Dapr Best Practices — Práticas recomendadas
- Dapr Patterns — Building blocks reference