Study Notes

RPC

Remote Procedural Call é um protocolo de comunicação em sistemas distribuídos. Chama uma função remota de forma que parece ser local (transparência de acesso). O marshalling (empacotamento) e unmarshalling (desempacotamento) de dados através de componentes chamados stubs.

Stub

São trechos de códigos gerados automaticamente pelo compilador que servem como proxy/middleware entre a comunicação via RPC. Dependendo da tecnologia, ele pode:

  • ser gerado automaticamente (ex: protoc do gRPC, rmic do Java RMI);
  • ou vir pronto numa biblioteca (ex: SDKs de APIs REST).

Client Stub

Para o programa cliente, ele se parece exatamente com o procedimento real. No entanto, sua função é "capturar" a chamada, empacotar (marshalling) os argumentos em uma mensagem e enviá-la para o servidor.

Skeleton

Recebe a mensagem do cliente, desempacota (unmarshalling) os argumentos, chama o procedimento local real e, quando a execução termina, empacota o resultado para enviá-lo de volta.

Semânticas

Em uma comunicação local, é possível ter certeza que a chamada de um método só acontecerá uma vez. No entanto, no RPC, como a chamada é via rede, o cliente pode enviar uma request e ficar sem response (timeout). Normalmente, o client stub então tenta reenviar a request, fazendo o comportamento de quantas vezes o procedimento remoto será de fato executado ser possivelmente não determinístico.

At Least Once

Nesta semântica, o cliente é persistente: ele continua reenviando a requisição até receber uma resposta do servidor. Garante que o procedimento será executado, mas pode ser executado mais de uma vez. Isso acontece se a resposta do servidor se perder e o cliente, pensando que a requisição falhou, a enviar novamente. É seguro usar esta semântica apenas para operações idempotentes, ou seja, operações que podem ser executadas várias vezes sem causar problemas ou efeitos colaterais. Por exemplo, consultar a hora ou o saldo de uma conta são operações seguras para esta semântica.

At Most Once

Esta semântica garante que o procedimento remoto será executado zero ou uma vez, mas nunca mais do que uma vez. Para implementar isso, cada chamada RPC recebe um identificador único. O servidor mantém um cache com os identificadores das chamadas que já processou. Se ele recebe uma requisição com um ID que já está no cache (uma duplicata), ele não executa o procedimento novamente; em vez disso, simplesmente reenvia o resultado que está armazenado. O Sun RPC utiliza essa abordagem. Evita os efeitos colaterais de múltiplas execuções, mas não garante que a operação será concluída (pode ser executada zero vezes se a mensagem nunca chegar ao servidor, mesmo com as retransmissões).

Exactly Once

Esta é a semântica ideal, que busca replicar o comportamento de uma chamada local, garantindo que o procedimento seja executado exatamente uma vez, sem falhas. Realidade: É a semântica desejada, mas é extremamente difícil de conseguir na prática em um sistema distribuído devido à imprevisibilidade da rede e às possíveis falhas do servidor. Ela é mais adequada para operações não idempotentes, como uma transferência bancária, onde a execução múltipla seria catastrófica.

Java RMI

Remote Method Invocation é a aplicação do RPC voltada para o Java e ao Paradigma de Orientação a Objetos.

O objetivo é o mesmo: permitir que um programa em uma máquina chame uma função em outra máquina de forma transparente. A grande diferença é que, em vez de chamar um procedimento (uma função solta), o RMI permite que você invoque um método de um objeto que está em outra JVM (Java Virtual Machine).

Interface Remota: Tudo em RMI começa com uma interface Java. Esta interface é o contrato que define quais métodos podem ser chamados remotamente. Ela precisa obrigatoriamente herdar de java.rmi.Remote, e todos os seus métodos devem declarar que podem lançar uma RemoteException.

Stub (Proxy do Cliente): É um objeto que fica no lado do cliente e se passa pelo objeto real. Quando você chama um método nele, o stub não executa a lógica; ele empacota os parâmetros (marshalling) e os envia pela rede para o servidor.

Skeleton (Esqueleto do Servidor): É a parte que fica no servidor. Ele recebe a mensagem da rede, desempacota os parâmetros (unmarshalling) e chama o método no objeto real que implementa a lógica de negócio.

RMI Registry

O rmiregistry é um Naming Service, análogo ao portmapper do Sun RPC. Ele funciona como um guia telefônico para objetos remotos.

O Servidor faz o rebind: Quando o servidor cria um objeto para ser acessado remotamente (ex: new CalculatorImpl()), ele o registra no Registry com um nome único (ex: "CalculatorService"). Isso é como publicar seu número de telefone no guia. O Cliente faz o lookup: Quando o cliente quer usar o objeto, ele contata o Registry (que roda em um endereço e porta conhecidos) e pede a referência para o objeto com o nome "CalculatorService". O Registry devolve o stub para o cliente.

Ou seja, o Registry é um daemon que roda em server side e mapeia/ fazem o binding de chamadas de métodos para as implementações de fato. Ou seja, o cliente precisa apenas saber o IP/DNS e a well-known port (1099) do registry. Dessa forma, o próprio serviço do registry irá vincular a chamada que chegou com a execução correta do método.

gRPC

JSON-RPC

Referências

On this page