Go e Dapr: Distributed Application Runtime
Simplifique microsserviços com Dapr em Go. Aprenda service invocation, state management, pub/sub e bindings com exemplos práticos.
Go e Dapr: Distributed Application Runtime
Dapr (Distributed Application Runtime) é uma plataforma portátil e event-driven que facilita a construção de aplicações distribuídas e microsserviços. Projetado pela Microsoft, é usado por empresas como Alibaba, Tencent e Ignition Group.
Neste guia, você aprenderá a usar Dapr com Go para resolver desafios comuns de microsserviços de forma simples e portátil.
Índice
- O que é Dapr?
- Arquitetura e Sidecar
- Configuração
- Service Invocation
- State Management
- Pub/Sub Messaging
- Bindings
- Observability
O que é Dapr?
Building Blocks
Dapr fornece 8 building blocks que resolvem problemas comuns:
Go e Temporal: Workflows Resilientes e Duráveis
Construa workflows resilientes com Temporal em Go. Aprenda about retries, sagas, signals e padrões de orquestração de processos distribuídos.
Go e Temporal: Workflows Resilientes e Duráveis
Temporal é uma plataforma de orquestração de workflows que permite criar processos de negócio resilientes, duráveis e escaláveis. Desenvolvido pelos criadores do Cadence (Uber), é amplamente adotado por empresas como Netflix, Stripe e Shopify.
Neste guia, você aprenderá a construir workflows complexos em Go com garantias de execução, retries automáticos e compensação (Saga pattern).
Índice
- Conceitos Fundamentais
- Configuração do Ambiente
- Primeiro Workflow
- Activities e Retries
- Saga Pattern
- Signals e Queries
- Timers e Cron Jobs
- Padrões Avançados
Conceitos Fundamentais
Arquitetura Temporal
┌─────────────────────────────────────────────────────────────┐
│ Temporal Server │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Frontend │ │ History │ │ Matching │ │
│ │ (gRPC) │ │ (Events) │ │ (Tasks) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ Persistence: PostgreSQL / MySQL / Cassandra / Elasticsearch│
└─────────────────────────────────────────────────────────────┘
│
│ gRPC
▼
┌─────────────────────────────────────────────────────────────┐
│ Workers (Go) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Workflow │ │ Activity │ │ Activity │ │
│ │ Engine │ │ Executor │ │ Executor │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ Workflows são determinísticos (replayable) │
│ Activities contêm side-effects (I/O, APIs) │
└─────────────────────────────────────────────────────────────┘
Conceitos Chave
Workflows: Funções Go que definem a lógica de negócio. São determinísticas e podem ser “replayed” indefinidamente.
Go e gRPC: Comunicação entre Serviços Completo
Aprenda a criar APIs eficientes com gRPC em Go. Tutorial completo cobrindo Protocol Buffers, streaming, interceptores e testes.
Go e gRPC: Comunicação entre Serviços
O gRPC tornou-se o padrão de facto para comunicação entre microserviços em ambientes de alta performance. Desenvolvido pelo Google, ele oferece vantagens significativas sobre REST tradicional, especialmente quando combinado com a eficiência do Go.
Neste tutorial completo, você vai aprender a construir serviços gRPC robustos em Go, desde o básico até técnicas avançadas como streaming bidirecional e interceptores.
Por Que Usar gRPC em Go?
gRPC vs REST: Comparativo
| Característica | REST/HTTP JSON | gRPC |
|---|---|---|
| Formato | JSON (texto) | Protocol Buffers (binário) |
| Performance | ~15x mais lento | ~15x mais rápido |
| Payload | Verbos, repetitivo | Compacto, eficiente |
| Tipagem | Fraca (runtime) | Forte (compile-time) |
| Streaming | Complicado (SSE/WebSocket) | Nativo e simples |
| Code Generation | Manual | Automático |
| Browser Support | Nativo | Requer gRPC-Web |
Quando escolher gRPC:
Go para Microserviços: Arquitetura e Práticas de Produção
Domine a arquitetura de microserviços em Go. Aprenda padrões de comunicação, service discovery, circuit breakers, distributed tracing e estratégias de deploy com exemplos práticos.
Microserviços transformaram a forma como desenvolvemos sistemas escaláveis. Go é a linguagem preferida para microserviços em empresas como Netflix, Uber, e Kubernetes. Neste guia completo, você aprenderá a arquitetar, construir e operar microserviços robustos em Go.
Por Que Go é Perfeito para Microserviços
O Match Perfeito
┌─────────────────────────────────────────────────────────────────┐
│ MICROSERVIÇO │ GO │
├─────────────────────────────────────────────────────────────────┤
│ Leve e rápido │ Binário único, startup < 100ms │
├─────────────────────────────────────────────────────────────────┤
│ Escalável │ Goroutines (milhões simultâneas) │
├─────────────────────────────────────────────────────────────────┤
│ Confiável │ Tipagem forte, sem runtime pesado │
├─────────────────────────────────────────────────────────────────┤
│ Eficiente │ Memória mínima (10-50MB por serviço) │
├─────────────────────────────────────────────────────────────────┤
│ Portátil │ Cross-compile, Docker nativo │
├─────────────────────────────────────────────────────────────────┤
│ Simples │ Código explícito, fácil manutenção │
└─────────────────────────────────────────────────────────────────┘
Comparação com Outras Linguagens
| Aspecto | Go | Java | Node.js | Python |
|---|---|---|---|---|
| Startup | ~50ms | ~5s | ~2s | ~1s |
| Memória | 10-50MB | 200-500MB | 100-300MB | 150-400MB |
| Concorrência | Nativa | Threads pesadas | Callbacks | GIL limita |
| Binário | Único | JVM necessária | Node runtime | Interpreter |
| Performance | Nativa | Boa (JIT) | Média | Lenta |
Arquitetura de um Microserviço Go
Estrutura de Projeto Recomendada
order-service/
├── cmd/
│ └── api/
│ └── main.go # Entry point
├── internal/
│ ├── domain/
│ │ ├── order.go # Entidades
│ │ └── errors.go # Erros de domínio
│ ├── application/
│ │ ├── service.go # Lógica de negócio
│ │ └── dto.go # Data Transfer Objects
│ ├── infrastructure/
│ │ ├── http/
│ │ │ ├── handler.go # HTTP handlers
│ │ │ ├── router.go # Configuração de rotas
│ │ │ └── middleware.go # Middlewares
│ │ ├── persistence/
│ │ │ ├── postgres.go # Implementação do repo
│ │ │ └── redis.go # Cache
│ │ └── messaging/
│ │ └── kafka.go # Event publisher
│ └── config/
│ └── config.go # Configurações
├── pkg/
│ └── logger/ # Shared packages
├── api/
│ └── proto/ # Protocol Buffers
├── deployments/
│ ├── docker/
│ └── k8s/
├── go.mod
└── Makefile
Implementação Completa
// internal/domain/order.go
package domain
import (
"errors"
"time"
)
var (
ErrInvalidAmount = errors.New("valor do pedido inválido")
ErrOrderNotFound = errors.New("pedido não encontrado")
)
type Order struct {
ID string `json:"id"`
UserID string `json:"user_id"`
Items []Item `json:"items"`
Total float64 `json:"total"`
Status Status `json:"status"`
CreatedAt time.Time `json:"created_at"`
}
type Item struct {
ProductID string `json:"product_id"`
Quantity int `json:"quantity"`
Price float64 `json:"price"`
}
type Status string
const (
StatusPending Status = "PENDING"
StatusPaid Status = "PAID"
StatusShipped Status = "SHIPPED"
StatusDelivered Status = "DELIVERED"
)
func (o *Order) CalculateTotal() {
var total float64
for _, item := range o.Items {
total += item.Price * float64(item.Quantity)
}
o.Total = total
}
func (o *Order) Validate() error {
if o.Total <= 0 {
return ErrInvalidAmount
}
return nil
}
// internal/application/service.go
package application
import (
"context"
"fmt"
"time"
"order-service/internal/domain"
)
// Portas (interfaces) para dependências
type OrderRepository interface {
Save(ctx context.Context, order *domain.Order) error
GetByID(ctx context.Context, id string) (*domain.Order, error)
Update(ctx context.Context, order *domain.Order) error
}
type PaymentService interface {
Process(ctx context.Context, orderID string, amount float64) error
}
type EventPublisher interface {
PublishOrderCreated(ctx context.Context, order *domain.Order) error
}
type OrderService struct {
repo OrderRepository
payment PaymentService
publisher EventPublisher
}
func NewOrderService(
repo OrderRepository,
payment PaymentService,
publisher EventPublisher,
) *OrderService {
return &OrderService{
repo: repo,
payment: payment,
publisher: publisher,
}
}
func (s *OrderService) CreateOrder(ctx context.Context, userID string, items []domain.Item) (*domain.Order, error) {
order := &domain.Order{
ID: generateID(),
UserID: userID,
Items: items,
Status: domain.StatusPending,
CreatedAt: time.Now(),
}
order.CalculateTotal()
if err := order.Validate(); err != nil {
return nil, err
}
// Salvar no banco
if err := s.repo.Save(ctx, order); err != nil {
return nil, fmt.Errorf("falha ao salvar pedido: %w", err)
}
// Publicar evento assíncrono
go func() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
s.publisher.PublishOrderCreated(ctx, order)
}()
return order, nil
}
func (s *OrderService) ProcessPayment(ctx context.Context, orderID string) error {
order, err := s.repo.GetByID(ctx, orderID)
if err != nil {
return err
}
if err := s.payment.Process(ctx, orderID, order.Total); err != nil {
return fmt.Errorf("pagamento falhou: %w", err)
}
order.Status = domain.StatusPaid
return s.repo.Update(ctx, order)
}
func generateID() string {
return fmt.Sprintf("ORD-%d", time.Now().UnixNano())
}
Padrões de Comunicação
1. Síncrono: HTTP REST
Já coberto no guia de APIs REST. Para microserviços, adicione: