RPC pode parecer sofisticado demais, mas que tal Request/Response? Agora "SOA" familiar? Nem só de total assincronismo vive o mundo da mensageria, há momentos em que precisamos de uma resposta. RPC é a forma mais prática de adotar mensageria, mas é preciso entender as consequências dessa abordagem.
Revisão 2
O que vou mostrar aqui é um padrão bem antigo, mas bem confuso para quem está começando. Trata-se do uso de filas para enviar e receber respostas. Enviar um request e receber um response.
O fato de ser um padrão conhecido, não o faz dele nem melhor nem pior. No entanto, o uso negligente e inadvertido de RPC com mensageria é um dos fatores de fracasso de projetos que conheço. E isso se dá por não entender as implicações dessa escolha.
Não basta usar filas, é preciso usar uma estratégia que traga os benefícios.
Afinal, o que é RPC?
Remote Procedure Call, ou a capacidade de chamar funções remotas usando uma infra assíncrona de mensageria como base. Embora o nome seja "procedure"/"procedimento", visualizamos mais fácil quando pensamos em Remote Function Call, já que estamos falando de algo com retorno.
É preciso uma coreografia
Para que esse fluxo funcione algumas coisas são necessárias:
O consumidor começa consumindo sua fila padrão. Aquela fila que tem um nome bonitinho e que é alcançada via uma exchange. Fila e exchange são pré estabelecidas.
O consumidor está pronto para receber uma mensagem e olhar um cabeçalho, que informa para qual fila enviar uma resposta.
Já o publisher antes de enviar a mensagem, precisa iniciar o consumo de uma fila anônima. Isso fará com que o RabbitMQ dê coo feedback o nome da fila anônima. Essa é nossa caixa postal para a resposta.
Uma vez de posse do nome da fila, basta consumir no modo exclusivo.
Agora estamos prontos para enviar uma mensagem. Mas agora usamos um cabeçalho replyto para indicar a fila de resposta. Dessa forma, o consumer será capaz de enviar a resposta para a fila e nosso publisher será capaz de receber essa resposta.
A coreografia
- Consumer Inicia consumo na fila padrão
- Publisher solicita ao RabbitMQ que crie uma fila anônima, exclusiva e autodelete. Essa será a fila de resposta.
- Publisher recebe o nome aleatório de fila, que já foi criada pelo RabbitMQ.
- Publisher inicia consumo exclusivo da fila anônima.
- Publisher prepara mensagem para o consumer, adicionando propriedade replyto no cabeçalho da mensagem. Essa propriedade contém o nome da fila anônima de resposta.
- Publisher envia mensagem para a fila padrão do consumer.
- Consumer recebe a mensagem
- Consumer realiza processamento (delegando para alguma camada de negócio)
- Consumer obtém o resultado.
- Consumer usa o cabeçalho replyto para publicar a resposta da mensagem na fila de resposta
- Publisher consome a mensagem
- Publisher cancela o consumo exclusivo, fazendo com que a fila exclusive e autodelete seja excluída.
- Publisher entrega response para o chamador.
O exemplo abaixo mostra isso.
Benefícios
Fácil adoção.
Não precisa revisitar os fluxos da aplicação, bastando reimplementar componentes com o protocolo.
Escalabilidade fácil de consumidores, permitindo que um consumidor falhe e mesmo assim o processo continue, sem que o publisher precise lidar com sequer 1 linha a mais de código.
Considerações
Se você disse que ficaria resiliente usando RabbitMQ, em qualquer cenário de RPC, isso não será verdade. A dependência da resposta fará com que sua aplicação aguarde esse feedback. Essa espera não pode ser infinita, e portanto dado um timeout você será afetado.
Se RPC não for uma exceção na sua implantação, muitas são as chances de você estar, na prática, forjando uma implantação de mensageria que não passa de uma fraude!
0 comentários