O que é o Watermill?
O Watermill é uma biblioteca open-source para Go, criada para facilitar o desenvolvimento de aplicações baseadas em eventos e mensagens. Ele abstrai a complexidade dos principais brokers do mercado (Kafka, RabbitMQ, NATS, Google Pub/Sub, Redis Streams, entre outros), oferecendo uma API unificada, simples e extensível. Com o Watermill, você pode construir pipelines de mensagens robustos, escaláveis e resilientes, sem se preocupar com os detalhes de cada sistema de mensageria.
Por que usar Watermill?
Sistemas baseados em eventos trazem vantagens como desacoplamento, escalabilidade horizontal e facilidade para implementar padrões como CQRS e Event Sourcing. O Watermill resolve problemas comuns desse tipo de arquitetura, como:
- Abstração dos brokers: troque Kafka por RabbitMQ (ou vice-versa) sem reescrever sua lógica.
- Middleware plugável: adicione logging, retries, métricas e outras funcionalidades de forma simples.
- Performance: processa centenas de milhares de mensagens por segundo, aproveitando o modelo concorrente do Go.
- Testabilidade: suporte a brokers em memória para testes locais rápidos.
Principais Componentes do Watermill
O Watermill é construído em torno de quatro conceitos principais:
- Publisher: responsável por publicar mensagens em um tópico.
- Subscriber: consome mensagens de um tópico.
- Router: roteia mensagens entre publishers e subscribers, aplicando middlewares e handlers.
- Middleware: adiciona funcionalidades transversais, como logging, retries, limitação de taxa, etc.
Esses componentes se conectam de forma flexível, permitindo criar desde fluxos simples até pipelines complexos de processamento de eventos.
Protocolos e Brokers Suportados
O Watermill suporta, de forma oficial, os principais sistemas de mensageria do mercado:
- Kafka
- RabbitMQ (AMQP)
- Google Cloud Pub/Sub
- AWS SNS/SQS
- Redis Streams
- SQL (PostgreSQL, MySQL)
- GoChannel (in-memory, ótimo para testes)
- HTTP
Isso significa que você pode começar com um broker simples e migrar para algo mais robusto conforme sua aplicação cresce, sem grandes mudanças no código.
Exemplo Prático: Publicando e Consumindo Mensagens com Kafka
Vamos ver um exemplo básico de como publicar e consumir mensagens usando Watermill com Kafka. O mesmo padrão vale para outros brokers, mudando apenas a configuração.
Pré-requisitos:
- Go instalado
- Docker rodando Kafka localmente (veja docker-compose aqui)
- Dependências instaladas:
go get github.com/ThreeDotsLabs/watermill
go get github.com/ThreeDotsLabs/watermill-kafka/v3
Publisher:
package main
import (
"github.com/ThreeDotsLabs/watermill"
"github.com/ThreeDotsLabs/watermill-kafka/v3/pkg/kafka"
"github.com/ThreeDotsLabs/watermill/message"
"log"
)
func main() {
logger := watermill.NewStdLogger(false, false)
publisher, err := kafka.NewPublisher(
kafka.PublisherConfig{
Brokers: []string{"localhost:9092"},
Marshaler: kafka.DefaultMarshaler{},
},
logger,
)
if err != nil {
log.Fatal(err)
}
msg := message.NewMessage(watermill.NewUUID(), []byte("Olá, Watermill!"))
if err := publisher.Publish("exemplo.topico", msg); err != nil {
log.Fatal(err)
}
log.Println("Mensagem publicada!")
}
Subscriber:
package main
import (
"context"
"github.com/ThreeDotsLabs/watermill"
"github.com/ThreeDotsLabs/watermill-kafka/v3/pkg/kafka"
"github.com/ThreeDotsLabs/watermill/message"
"log"
)
func main() {
logger := watermill.NewStdLogger(false, false)
subscriber, err := kafka.NewSubscriber(
kafka.SubscriberConfig{
Brokers: []string{"localhost:9092"},
Unmarshaler: kafka.DefaultMarshaler{},
ConsumerGroup: "exemplo-grupo",
},
logger,
)
if err != nil {
log.Fatal(err)
}
messages, err := subscriber.Subscribe(context.Background(), "exemplo.topico")
if err != nil {
log.Fatal(err)
}
for msg := range messages {
log.Printf("Mensagem recebida: %s", string(msg.Payload))
msg.Ack()
}
}
Dica:
Para testar localmente, rode o Kafka com Docker, execute o subscriber e depois o publisher. Você verá as mensagens fluindo entre eles.
Casos de Uso e Vantagens
O Watermill é ideal para:
- Microsserviços que precisam se comunicar de forma assíncrona e desacoplada.
- Sistemas de processamento de eventos em tempo real (monitoramento, analytics, notificações).
- Implementação de padrões como CQRS e Event Sourcing.
- Projetos que exigem escalabilidade horizontal e resiliência.
Entre as vantagens, destacam-se a flexibilidade (suporte a múltiplos brokers), performance, API intuitiva e facilidade de integração com middlewares e métricas (Prometheus).
Conclusão
O Watermill é uma excelente escolha para quem quer adotar event-driven architecture e mensageria em Go. Ele abstrai a complexidade dos brokers, oferece uma API poderosa e flexível, e permite construir sistemas modernos, escaláveis e resilientes. Se você quer dar o próximo passo na arquitetura do seu projeto Go, vale muito a pena experimentar o Watermill.
Links úteis:
Se ficou com dúvidas ou quer compartilhar sua experiência com Watermill, deixe um comentário!