System Design/02 - Componentes/Communication2 min
RPC
- Que problema isso resolve?
- Quando usar / quando NÃO usar?
- Qual o principal trade-off?
- Como isso falha em produção?
Conceito
Remote Procedure Call: fazer uma chamada de rede parecer uma chamada de função local.
resultado = servico.calcular(a, b) // parece local
// é rede: serializa, envia, espera, desserializa
Peças: um stub no cliente, uma serialização (JSON, Protobuf, Thrift), um transporte, e um skeleton no servidor que desempacota e chama a função real.
Implementações
| Tecnologia | Serialização | Nota |
|---|---|---|
| gRPC | Protobuf | O padrão atual (gRPC) |
| Thrift | Binário | |
| JSON-RPC | JSON | Simples, sobre HTTP |
| SOAP/XML-RPC | XML | Legado, verboso |
| CORBA, DCOM | Binário | Histórico |
RPC vs REST
| RPC | REST | |
|---|---|---|
| Modelo mental | Ação — criarPedido() |
Recurso — POST /pedidos |
| Acoplamento | Maior (assinatura) | Menor (contrato uniforme) |
| Cache HTTP | Difícil | Natural |
| Descoberta | Precisa de IDL | Auto-descritivo |
Trade-offs
A promessa do RPC — "rede parece função local" — é também sua crítica mais antiga, formalizada nas Falácias da Computação Distribuída. A rede não é como uma chamada local:
| Falácia | Realidade |
|---|---|
| A rede é confiável | Ela falha, e falha parcialmente |
| Latência é zero | É 10⁶ vezes maior que uma chamada local |
| Banda é infinita | Payload grande custa |
| A topologia não muda | Muda o tempo todo |
| Transporte é gratuito | Serialização custa CPU |
Esconder a rede faz o programador esquecer que a chamada pode demorar, falhar, ou ter sido executada sem que a resposta chegue. Chamadas RPC em laço produzem Chatty IO; chamadas sem timeout travam threads; chamadas sem Circuit Breaker propagam falha em cascata.
RPC continua sendo a escolha certa para comunicação interna de alta frequência — desde que o código trate cada chamada como o que ela é: uma operação de rede, com timeout, retry e tratamento de falha explícitos.
Exemplo prático
// parece local, mas cada linha é uma ida à rede
Usuario u = usuarioService.buscar(id); // 5 ms
Endereco e = enderecoService.buscar(u.enderecoId); // 5 ms
List<Pedido> p = pedidoService.listar(id); // 5 ms
Três chamadas encadeadas, 15 ms — e três chances de falha, cada uma capaz de travar a thread se não houver timeout. Num laço sobre 100 usuários, viram 1.500 ms e 300 pontos de falha.
A correção é tratar a rede como rede: uma chamada em lote (buscarVarios(ids)) em vez de N chamadas, com timeout e circuit breaker explícitos. É o antídoto de Chatty IO — e ele só aparece quando o programador não esquece que aquilo é RPC.
Relacionado
Parte de Communication · roadmap.sh/system-design