PauloSouza.info
Posted on June 23, 2022
Atualmente, quando falamos de PubSub, temos inúmeras opções para discutir quando falamos de clientes e servidores.
Basicamente, temos um publicador de um lado e um ouvinte do outro aguardando um dado. De forma simplificada — caso você ainda não tenha lido sobre isso, é como o professor lá na frente explicando uma matéria e do outro lado, 40 alunos na mesma sala anotando tudo aquilo que escutam.
Bem fácil, né?
Sistemas já conhecidos de mensageiros como RabbitMQ, ZeroMQ, Kafka e Nats.io promovem para cada solução, uma forma de implantar isso no seu código onde a distribuição dos dados mesmo que em ambientes diferentes, possa ser propagado com segurança.
No navegador, para uma comunicação através de um Websocket ou EventSource, também temos um publicador e múltiplos ouvintes como em uma sala de bate-papo, mas de formas distintas. O Websocket é um sistema de 2 vias onde ele pode ser o publicador e ouvinte, enquanto no EventSource uma única via é utilizada na comunicação do servidor com os clientes.
O Redis, conhecido pela sua velocidade, já possui nativamente a funcionalidade para PubSub sem a necessidade de configurações adicionais, mas com suas limitações onde nas ferramentas citadas teremos soluções mais robustas, com persistência de dados, streaming e por aí vai... Mas estamos aqui para falar do Redis PubSub.
Botando o Redis pra funcionar
Para testes, você pode subir um container na sua máquina mesmo para o Redis utilizando o Docker.
docker run -ti --rm -p 6379:6379 --name pubsub redis:alpine
Como Redis ativo, abra uma nova aba/janela da sua linha de comando para testarmos o canal pythonpubsub como ouvinte.
docker exec -ti pubsub redis-cli subscribe pythonpubsub
Para testarmos a publicação no mesmo canal, abra uma nova aba/janela na sua linha de comando e vamos ver a máquina acontecer.
docker exec -ti pubsub redis-cli publish pythonpubsub "eu sou uma mensagem"
Divertido, né?... Mas aí você se pergunta sobre a velocidade e nesta aba/janela que você publicou a mensagem, vamos fazer um for simples para publicar 10000 mensagens.
for i in {1..10000}; do
docker exec -ti pubsub redis-cli publish pythonpubsub "mensagem $i";
done
Agora que configuramos o ambiente como container Redis e testamos o PubSub, feche todas as janelas mantendo apenas a aba/janela da sua linha de comando onde o servidor Redis está rodando. Tá na hora de escrever um código bem simples em Python. Tão simples que é bem próximo do que fizemos até agora e isso vai ampliar seus horizontes.
Partindo para o código em Python
Mas... Python? Só Python? Não! O exemplo é em Python - por uma paixão pessoal e ser melhor na leitura do código, mas pode ser também com o uso de bibliotecas equivalentes para NodeJS, PHP, Golang, Java ou qualquer outra linguagem da sua preferência.
Aqui, na minha máquina local, eu estou usando o Python na versão 3.9.13, mas em testes recentes eu não tive problema de compatibilidade em versões 3.6+.
No caso do Python, é sempre importante ter o ambiente virtual ativo para que assim possamos isolar as dependências entre projetos.
python3 -m venv venv
Inicie o ambiente virtual para iniciar a instalação da única dependência que teremos com a biblioteca de conexão para o Redis.
. venv/bin/activate
Instale a biblioteca redis.
pip3 install redis
Crie um arquivo chamado app.py e nele, vamos inserir o nosso código de subscriber como um daemon que se manterá ativo até o encerramento do programa (o famoso ctrl+c).
from redis import StrictRedis
client = StrictRedis(host="localhost", port=6379)
pubsub = client.pubsub()
pubsub.subscribe('pythonpubsub')
while True:
msg = pubsub.get_message()
if msg:
if not isinstance(msg['data'], int):
channel, message = msg['channel'], msg['data']
print('%s: %s' % (channel.decode('utf-8'), message.decode('utf-8')))
Rode o arquivo app.py.
python3 app.py
Junto com a aplicação já rodando, abra outra aba/janela na sua linha de comando e deixe o subscriber do Redis rodando do lado.
docker exec -ti pubsub redis-cli subscribe pythonpubsub
Sabe aquele for que criamos lá em cima? Abra uma nova aba/janela da sua linha de comando e vamos ver as mensagens sendo propagadas em ambas as janelas.
for i in {1..10000}; do
docker exec -ti pubsub redis-cli publish pythonpubsub "mensagem $i";
done
Bem legal, né? Vou te falar que isso já me salvou algumas vezes para aumentar a velocidade de processamento paralelo em algumas aplicações sem grandes mudanças ou necessidade de refactoring.
Espero que você tenha curtido. Sigo aberto a sugestões e boas idéias.
Posted on June 23, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.