- A comunicação é uma necessidade básica dos seres humanos.
- A forma de comunicação evolui ao longo do tempo.
- A comunicação possui três elementos fundamentais: remetente, mensagem e destinatário.
- O remetente é aquele que envia a informação, o destinatário é aquele que recebe a informação e a mensagem é a informação propriamente dita.
- O destinatário pode confirmar a chegada através de resposta única ou múltiplas respostas.
- O nosso modelo de comunicação é muito semelhante com a comunicação das aplicações que criamos.
- O modelo cliente-servidor segue os pilares da comunicação.
- Os termos síncrono e assíncrono referem-se ao fluxo de uma aplicação.
- Uma aplicação síncrona é aquela em que um processo é realizado somente quando o processo anterior termina.
- Uma comparação com o mundo real seria o "subir de uma escada" em que para subir um degrau é preciso ter subido o degrau anterior.
- Um exemplo de processo assíncrono comprar um ingresso que envolve os passos (1) escolher o ingresso, (2) enviar confirmação, (3) processar pagamento e (4) enviar o ingresso.
- Uma aplicação assíncrona é aquela em que um processo pode ser realizado mesmo que o processo anterior não tenha terminado.
- Um publisher é aquele que envia a mensagem (remetente).
- Um consumer é aquele que recebe a mensagem (destinatário).
- Um message broker é responsável por intermediar as mensagens enviadas.
- Um message broker pode ser comparado a um correio.
- A utilização de um sistema de mensageria permite desacoplar os elementos de uma aplicação e facilita a escalabilidade da mesma.
- Isso torna a aplicação flexível permitindo adicionar ou remover serviços com facilidade e com melhor desempenho devido ao processamento assíncrono.
- O message broker pode utilizar diversos protocolos.
- Um dos protocolos mais conhecidos é o AMQP.
- O AMQP ou Advanced Message Queuing Protocol é um protocolo open-source, que permite a interoperabilidade entre microsserviços e define o padrão da mensagem.
- O message broker possui os seguintes elementos:
- virtual host - camada de segurança
- exchange - responsável pelo roteamento das mensagens
- queue - fila que vai receber essas mensagens
- binding - conexão entre a exchange e a queue
- O ciclo completo de uma mensagem no RabbitMQ é representado por publisher -> broker -> channel -> consumer. Os elementos possuem as seguintes responsabilidades:
- publisher - publica uma mensagem
- broker - processa a mensagem
- channel - conexão lógica entre o broker e o consumer
- faz com que não se tenha custo com conexão TCP
- consumer - recebe a mensagem
- O RabbitMQ é uma ferramenta de mensageria open source escrita em Erlang.
- O Erlang possui alta confiabilidade em sistemas distribuídos, isto é, área em que a linguagem possui destaque.
- O RabbitMQ suporta diversos sistemas operacionais e linguagens e possui muitos plugins.
- Pode-se ter um publisher escrito em Java e um consumer escrito em Go.
- O RabbitMQ pode utilizar diferentes topologias como standalone, cluster ou federation (possui dois clusters que se comunicam).
- Para uma instalação básica do RabbitMQ é necessário:
- instalação do servidor do RabbitMQ
- instalação do painel de gerenciamento (plugin)
- configuração do virtual host e usuário
- Para instalar o servidor do RabbitMQ no Ubuntu utiliza-se o comando
sudo apt-get install rabbitmq-server
.
- Após a instalação do painel de gerenciamento é possível acessá-lo via navegador utilizando interface gráfica.
- Após a instalação inicial recomenda-se restringir os acessos a ferramenta de fila.
- Pode-se realizar o gerenciamento de usuários via linha de comando utilizando o utilitário
rabbitmqctl
.
# altera a senha do usuário
sudo rabbitmqctl change_password guest p455w0rd`
# adiciona novo usuário
sudo rabbitmqctl set_user john.doe p455w0rd
# adiciona o usuário em um grupo
sudo rabbitmqctl add_user_tag john.doe administrator
- Pode-se também realizar o gerenciamento de usuário via interface gráfica.
- Para criar um publisher é necessário:
- criar uma conexão
- criar um channel
- declarar uma fila em um channel
- criar uma mensagem
- enviar a mensagem para uma exchange
- Ao criar uma fila precisamos definir os parâmetros:
- name - nome da fila
- durable - se a fila existirá após um reinício
- auto_delete - se a fila termina ou não após a última mensagem
- nowait - se a fila precisa esperar por alguma resposta ou não
// producer
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
$channel->queue_declare('my_queue', false, false, false, false);
$message = new AMQPMessage('Hello world!');
$channel->basic_publish($message, '', 'my_queue');
$channel->close();
$connection->close();
- Para criar um consumer é necessário:
- criar uma conexão
- criar um channel
- declarar uma fila em um channel
- criar uma função de callback
- consumir mensagens de uma fila
// consumer
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
$channel->queue_declare('my_queue', false, false, false, false);
$callback = function ($message) {
echo $message->body;
};
$channel->basic_consume('my_queue', false, true, false, false, $callback);
while(count($channel->callbacks)) {
$channel->wait();
}
$channel->close();
$connection->close();
- Deve-se informar ao message broker a forma de roteamento de mensagens.
- Os tipos de exchanges são:
- fanout exchange
- envia a mensagem para todas as filas existentes
- funciona como um ventilador
- quando a mensagem é consumida com sucesso, a mensagem é eliminada das outras filas
$channel->exchange_declare('my_queue', 'fanout', false, false, false)
- direct exchange
- envia a mensagem parauma fila específica
- por exemplo: direcionar uma mensagem para filas específicas como archive, crop ou resize
- cada consumer que tem e que pega cada fila pode ter funcao diferente
- cada fila pode ter uma função diferente
- topic exchange
- possui o funcionamento semelhante a direct exchange
- utiliza tópicos (*.web, *.email, *.log) para decidir a fila
- headers exchange
- possui o funcionamento semelhante a direct exchange
- utiliza dados do cabeçalho como routing key
- Existem algumas soluções interessantes para se trabalhar com filas como dead letter queue, multi propósito e delayed message.
- Um dead letter queue é quando um consumidor não consegue consumir uma mensagem, ela então é devolvida para uma exchange e direcionada para uma fila de mensagens rejeitadas.
- Uma mensagem não pode ser perdida pois pode ser algo importante para outras partes do sistema.
- Por exemplo: uma mensagem responsável por enviar uma requisição para a API dos Correios mas a API está fora do ar.
- Essa fila de mensagens rejeitadas pode ser reprocessada posteriormente.
- A solução multi-propósito consiste em enviar uma mensagem para a fila, o roteador faz a separação conforme e um consumidor envia para serviços diferentes como e-mail, cloud ou banco de dados.
- A solução delayed message é semelhante a dead letter queue e é utilizada quando precisamos atrasar uma mensagem.
- Neste caso, envia-se uma mensagem para uma fila de delay que, por sua vez, não encontrará nenhum consumidor. A mensagem é, então, enviada novamente para uma exchange que a redireciona para uma fila que será processada posteriormente.
- O site do RabbitMQ possui uma ótima documentação e possui um tutorial interativo.
- Outras duas referências são os livros RabbitMQ Essentials e RabbitMQ Cookbook.