Visão geral do projeto
Arquivos-fonte
Esta página foi gerada com base nos seguintes arquivos-fonte:
O gochat é um sistema de mensageria instantânea (IM) leve, implementado inteiramente em Go puro, projetado para oferecer comunicação em tempo real com suporte a mensagens privadas e broadcast em salas. O sistema destaca-se pela arquitetura modular baseada em RPC, permitindo escalabilidade horizontal de cada camada independentemente. Com suporte simultâneo a conexões WebSocket e TCP, o gochat utiliza etcd para descoberta de serviços e Redis como transporte de mensagens, criando uma solução adequada para cenários que exigem comunicação bidirecional de baixa latência (readme.md:19-26).
O projeto foi desenvolvido com foco em simplicidade de deployment e clareza arquitetural, oferecendo Docker para construção unificada do ambiente e compilação cruzada nativa do Go para múltiplas plataformas. A estrutura de diretórios separa claramente as responsabilidades entre camadas de conexão, lógica de negócio, API REST e consumo de tarefas, facilitando a manutenção e extensão do sistema (readme.md:1-12).
Introdução e Características do Sistema
O gochat posiciona-se como uma solução de IM (Instant Messaging) de código aberto que prioriza leveza e clareza arquitetural. O sistema suporta dois modos principais de comunicação: mensagens privadas (diretas entre usuários) e broadcast de salas (mensagens entregues a todos os participantes de uma sala). A comunicação entre camadas ocorre exclusivamente via RPC, utilizando a biblioteca rpcx, o que permite que cada componente seja escalado horizontalmente de forma independente conforme a demanda (readme.md:19-26).
Características Principais
| Característica | Descrição | Benefício |
|---|---|---|
| Go Puro | Implementação 100% em Go sem bindings C | Compilação cruzada simples, binários estáticos |
| WebSocket + TCP | Suporte simultâneo a ambos os protocolos | Flexibilidade para diferentes tipos de clientes |
| RPC entre camadas | Comunicação via rpcx com etcd | Escalabilidade horizontal transparente |
| Redis como message broker | Filas para desacoplamento de produtores/consumidores | Substituível por Kafka/RabbitMQ em produção |
| Descoberta de serviço | etcd para registro e descoberta dinâmica | Adição/remoção de nós sem reconfiguração |
| Snowflake ID | Gerador de IDs distribuídos | QPS teórico de 409.6w/s para IDs únicos |
O sistema foi projetado para demonstrar padrões arquiteturais de sistemas de chat em produção, utilizando componentes que podem ser substituídos por alternativas mais robustas conforme a escala. O Redis, utilizado para filas e cache, pode ser substituído por Kafka ou RabbitMQ; o SQLite, usado para demonstração, pode ser substituído por MySQL ou PostgreSQL com mudanças mínimas no driver (readme.md:150-173).
Capacidades Quantificáveis
- 6 módulos independentes: api, connect_websocket, connect_tcp, logic, task, site
- 2 protocolos de transporte: WebSocket (porta 7000) e TCP (portas 7001-7002)
- 1 ponto de entrada unificado:
main.gocom seleção de módulo via flag-module - Suporte a Go 1.18+: Requerido para compilação com generics e otimizações recentes
- Arquitetura de 5 camadas: Connect, Logic, Task, API, Site - todas escaláveis horizontalmente
Arquitetura e Design do Sistema
A arquitetura do gochat segue o padrão de separação em camadas com comunicação assíncrona via filas. O fluxo de mensagens é desacoplado através de Redis, permitindo que a camada de conexão (Connect) foque exclusivamente em manter conexões long-lived com clientes, enquanto a camada de lógica (Logic) processa regras de negócio e a camada de tarefas (Task) consome mensagens para entrega final (readme.md:64-68).
正在加载图表渲染器...
O diagrama acima ilustra a separação de responsabilidades entre as seis camadas do sistema. A camada Connect é responsável por manter conexões persistentes com clientes (WebSocket ou TCP), enquanto a camada Logic processa requisições RPC de ambas as camadas Connect e API. Mensagens são persistidas em filas Redis e consumidas pela camada Task, que então realiza broadcast via RPC para todas as instâncias Connect relevantes (readme.md:71-75).
Padrão de Descoberta de Serviço
O etcd atua como registro centralizado para descoberta de serviço. Cada instância de módulo registra-se no etcd ao iniciar, permitindo que outras camadas descubram dinamicamente os endpoints disponíveis. Quando uma nova instância Connect é adicionada, ela é automaticamente descoberta pela camada Task, que passa a enviar mensagens para ela via RPC. Este padrão elimina a necessidade de configuração estática de endpoints e suporta scaling automático (readme.md:64-68).
Fluxo de Entrega de Mensagens
O fluxo de mensagens no gochat segue um padrão producer-consumer desacoplado:
- Produção: Mensagens são enviadas via HTTP para a API ou diretamente via WebSocket/TCP
- Processamento: A camada Logic valida e empurra mensagens para filas Redis
- Consumo: A camada Task consome mensagens das filas
- Broadcast: Task realiza RPC call para todas as instâncias Connect relevantes
- Entrega: Connect entrega mensagens aos clientes conectados via WebSocket ou TCP
Este padrão garante que falhas temporárias em qualquer camada não resultem em perda de mensagens, desde que Redis esteja configurado com persistência adequada (readme.md:71-75).
Estrutura de Diretórios e Módulos
A organização do código reflete a separação arquitetural em camadas, com cada diretório representando um módulo independente que pode ser compilado e deployado separadamente. O ponto de entrada unificado em main.go utiliza flags para selecionar qual módulo executar, simplificando o processo de build e deployment (main.go:21-43).
text1gochat/ 2├── api/ # Camada API REST 3├── architecture/ # Diagramas e recursos visuais 4├── bin/ # Binários compilados (não versionados) 5├── config/ # Arquivos de configuração 6├── connect/ # Camada de conexão (WebSocket + TCP) 7├── db/ # Conexões de banco de dados 8├── docker/ # Dockerfile e scripts de build 9├── logic/ # Camada de lógica de negócio 10├── main.go # Ponto de entrada unificado 11├── proto/ # Definições RPC/protobuf 12├── site/ # Interface web estática 13├── task/ # Camada de consumo de tarefas 14├── tools/ # Utilitários compartilhados 15└── vendor/ # Dependências vendorizadas
Análise dos Módulos Principais
Módulo Connect (connect_websocket e connect_tcp)
Responsabilidade: Manter conexões long-lived com clientes, gerenciar sessões de sala e entregar mensagens em tempo real. Não processa lógica de negócio - apenas recebe mensagens do cliente e encaminha para a camada Logic via RPC, além de receber broadcasts da camada Task para entrega aos clientes (readme.md:124-148).
Entrada e APIs:
- Flag
-module connect_websocketou-module connect_tcpemmain.go:29-32 - RPC server para receber broadcasts da camada Task
- WebSocket handler na porta 7000 ou TCP listener nas portas 7001-7002
Estruturas de Dados:
- Mapa de sessões por sala (dupla lista encadeada de conexões)
- Contexto de conexão com informações de autenticação e roomId
Fluxo de Chamadas:
- Cliente conecta via WebSocket/TCP com authToken
- Connect valida token e associa conexão à sala
- Mensagens do cliente são encaminhadas via RPC para Logic
- Broadcasts de Task são recebidos e entregues aos clientes da sala
Módulo Logic
Responsabilidade: Processar regras de negócio, validar mensagens, gerenciar autenticação e autorização, e empurrar mensagens validadas para filas Redis. Atua como intermediário entre Connect/API e o sistema de filas (readme.md:124-148).
Entrada e APIs:
- Flag
-module logicemmain.go:27-28 - RPC server recebendo chamadas de Connect e API
- Métodos RPC para envio de mensagens, autenticação, gerenciamento de salas
Estruturas de Dados:
- Requisições RPC com payload de mensagem, metadados de usuário
- Respostas RPC com status de validação e IDs gerados
Fluxo de Chamadas:
- Recebe RPC call de Connect ou API
- Valida autenticação e autorização
- Aplica regras de negócio (rate limiting, filtros)
- Gera ID via Snowflake
- Empurra mensagem para fila Redis apropriada
Módulo Task
Responsabilidade: Consumir mensagens de filas Redis e realizar broadcast para instâncias Connect apropriadas. Implementa o padrão consumer com retry e garantia de entrega (readme.md:124-148).
Entrada e APIs:
- Flag
-module taskemmain.go:33-34 - Consumer de filas Redis
- RPC client para chamadas broadcast para Connect
Fluxo de Chamadas:
- Consome mensagem de fila Redis
- Identifica salas/destinatários
- Descobre instâncias Connect via etcd
- Realiza RPC call para cada instância Connect
- Connect entrega mensagem aos clientes conectados
Módulo API
Responsabilidade: Expor REST API para clientes externos, gerenciar autenticação HTTP, e atuar como gateway para a camada Logic via RPC (readme.md:124-148).
Entrada e APIs:
- Flag
-module apiemmain.go:35-36 - HTTP server com endpoints REST
- RPC client para Logic
Endpoints Principais:
/login- Autenticação de usuário/register- Registro de novo usuário/send- Envio de mensagem (HTTP como alternativa a WebSocket)
Ponto de Entrada Unificado
O arquivo main.go implementa um ponto de entrada unificado que seleciona o módulo a executar via flag -module. Este design simplifica o processo de build, pois apenas um binário precisa ser compilado para todos os módulos. A seleção ocorre em um switch statement que invoca a função Run() apropriada para cada módulo (main.go:21-43).
go1// Ponto de entrada com seleção de módulo via flag 2switch module { 3case "logic": 4 logic.New().Run() 5case "connect_websocket": 6 connect.New().Run() 7case "connect_tcp": 8 connect.New().RunTcp() 9case "task": 10 task.New().Run() 11case "api": 12 api.New().Run() 13case "site": 14 site.New().Run() 15default: 16 fmt.Println("exiting,module param error!") 17 return 18}
O tratamento de sinais de sistema (SIGHUP, SIGINT, SIGTERM, SIGQUIT) garante shutdown gracioso, permitindo que conexões ativas sejam finalizadas adequadamente antes do término do processo (main.go:44-47).
Stack Tecnológica e Dependências
O gochat utiliza uma stack tecnológica moderna com foco em performance e simplicidade operacional. A escolha de Go 1.18+ como linguagem base proporciona compilação cruzada nativa, garbage collection eficiente e concorrência via goroutines, essenciais para sistemas de alta concorrência como IM (go.mod:1-22).
Componentes Principais
| Componente | Versão | Propósito | Alternativas em Produção |
|---|---|---|---|
| Go | 1.18+ | Linguagem base | - |
| Gin | 1.7.7 | HTTP framework para API | Echo, Fiber |
| rpcx | 1.7.4 | Framework RPC com etcd | gRPC, Twirp |
| etcd | via rpcx-etcd | Descoberta de serviço | Consul, ZooKeeper |
| Redis | 6.15.9 | Filas, cache, sessões | Kafka, RabbitMQ |
| GORM | 1.9.16 | ORM para banco de dados | sqlx, ent |
| SQLite | via go-sqlite3 | Banco de dados (demo) | MySQL, PostgreSQL |
| Gorilla WebSocket | 1.5.0 | Protocolo WebSocket | nhooyr.io/websocket |
| Snowflake | 0.3.0 | Geração de IDs únicos | UUID, ULID |
| Viper | 1.11.0 | Gerenciamento de configuração | envconfig |
Dependências de Infraestrutura
O sistema depende de três componentes de infraestrutura externos que devem estar disponíveis antes da inicialização:
-
etcd: Registro para descoberta de serviço. Cada módulo registra-se ao iniciar e descobre outros módulos dinamicamente. A atualização de 2022 adicionou watch para mudanças de KV, permitindo detecção automática de novas instâncias (readme.md:150-173).
-
Redis: Atua como message broker e cache. Filas são utilizadas para desacoplar produtores (Logic) de consumidores (Task). Sessões de usuário e contadores também são armazenados aqui.
-
Banco de Dados: SQLite é usado para demonstração com GORM como abstração, permitindo substituição por MySQL ou PostgreSQL com mudanças mínimas no driver (go.mod:11).
Bibliotecas Auxiliares
Além dos componentes principais, o projeto utiliza bibliotecas auxiliares para funcionalidades específicas:
- pkg/errors (0.9.1): Tratamento de erros com stack traces
- sirupsen/logrus (1.8.1): Logging estruturado
- google/uuid (1.3.0): Geração de UUIDs
- rcrowley/go-metrics (0.0.0-20201227073835-cf1acfcdf475): Métricas de aplicação
O arquivo go.mod define o módulo como gochat com Go 1.18, garantindo compatibilidade com features como generics e otimizações do compilador. Dependências são vendorizadas no diretório vendor/, permitindo builds offline e garantindo reprodutibilidade (go.mod:1-3).
Interoperabilidade WebSocket e TCP
Uma característica distintiva do gochat é o suporte simultâneo a conexões WebSocket e TCP, com interoperabilidade completa entre clientes de diferentes protocolos na mesma sala. Esta funcionalidade permite que clientes web utilizem WebSocket enquanto clientes mobile ou IoT utilizem TCP raw, todos participando do mesmo ecossistema de mensagens (readme.md:37-60).
Mecanismo de Autenticação
A autenticação TCP utiliza um token (authToken) enviado pelo cliente após estabelecer a conexão. Este token é o mesmo retornado pela API de login web, permitindo que usuários alternem entre WebSocket e TCP com a mesma identidade. O servidor Connect valida o token, recupera informações do usuário e associa a conexão TCP à sala apropriada (readme.md:46-49).
Fluxo de Mensagens Misto
正在加载图表渲染器...
O diagrama de sequência acima ilustra o fluxo completo de uma mensagem em um cenário com clientes mistos. A chave da interoperabilidade está na camada Connect, que mantém um mapa unificado de sessões por sala, independentemente do protocolo de transporte. Quando a camada Task realiza broadcast para uma sala, a camada Connect itera sobre todas as conexões (WebSocket e TCP) e entrega a mensagem usando o protocolo apropriado para cada cliente (readme.md:51-59).
Implementação TCP: Desafios de Streaming
TCP é um protocolo de camada 4 baseado em stream, não em mensagens. Para delimitar mensagens no stream, o gochat implementa um protocolo de framing com operações de Pack (empacotamento) e Unpack (desempacotamento). O arquivo stickpackage.go no diretório pkg/ contém esta lógica, que é invocada tanto no servidor quanto no cliente TCP (readme.md:40-43).
Estrutura do Frame TCP:
- Header: 4 bytes indicando tamanho do payload
- Payload: Mensagem serializada (JSON ou protobuf)
Clientes Android/iOS devem implementar o mesmo protocolo de framing para comunicação TCP. O repositório inclui um cliente de teste em Go (stickpackage_test.go) que demonstra a implementação correta (readme.md:43-44).
Inicialização Separada de Módulos
O ponto de entrada main.go trata WebSocket e TCP como módulos separados, permitindo que sejam deployados independentemente. A função connect.New().Run() inicializa o servidor WebSocket, enquanto connect.New().RunTcp() inicializa o servidor TCP. Esta separação permite escalar cada protocolo independentemente conforme a demanda (main.go:29-32).
go1case "connect_websocket": 2 connect.New().Run() 3case "connect_tcp": 4 connect.New().RunTcp()
Cenários de Uso e Aplicabilidade
O gochat é adequado para diversos cenários que exigem comunicação em tempo real com arquitetura escalável:
Chat em Tempo Real
Sistemas de chat público ou privado com suporte a salas e mensagens diretas. A arquitetura de filas permite processamento assíncrono de mensagens com garantia de entrega.
Notificações Push
Sistemas de notificação em tempo real onde mensagens precisam ser entregues a usuários conectados. A camada Task pode ser estendida para integrar com serviços de push notification externos.
Dashboards em Tempo Real
Atualização de dashboards com dados em tempo real via WebSocket. A estrutura de salas pode ser utilizada para agrupar usuários por contexto (ex: sala por projeto ou empresa).
Sistemas de Colaboração
Editores colaborativos, whiteboards ou qualquer aplicação que exija sincronização de estado em tempo real entre múltiplos clientes.
Limitações Conhecidas
- Persistência de Mensagens: Mensagens não são persistidas em banco de dados por padrão, apenas transitam pelas filas. Implementação de persistência requer extensão da camada Logic (readme.md:273-274).
- SQLite em Produção: O banco SQLite é adequado apenas para demonstração. Deployments de produção devem utilizar MySQL ou PostgreSQL.
- Redis como Fila: Para alta escala, Redis pode não oferecer garantias de entrega equivalentes a Kafka. Avaliar requisitos de durabilidade antes de deploy em produção.
Roteiro de Leitura do Relatório
Para maximizar a compreensão do sistema gochat, recomenda-se a seguinte sequência de leitura dos capítulos deste relatório técnico:
正在加载图表渲染器...
Sequência Recomendada:
- Visão Geral (capítulo atual): Introdução ao sistema, características principais e stack tecnológica
- Arquitetura do Sistema: Análise detalhada da separação em camadas, padrões de comunicação e descoberta de serviço
- Modelo de Dados: Estruturas de dados, esquemas de banco de dados e fluxo de persistência
- Design de API: Endpoints REST, contratos RPC e padrões de autenticação
- Deployment: Configuração Docker, variáveis de ambiente e procedimentos de operação
Este roteiro progressivo permite que desenvolvedores compreendam primeiro o contexto geral antes de mergulhar em detalhes de implementação específicos.
