A necessidade de criar um servidor WebSocket
Hoje tenho um cenário onde estamos criando uma plataforma de e-commerce voltada para ensino a distância.
Decidimos abandonar o modelo de aplicação monolítica para trabalhar com uma aplicação distribuída usando o conceito de API First assim, nossa primeira etapa do projeto foi começar a desenvolver as APIs.
Desde o início do projeto já tínhamos em mente que algumas APIs teriam que ser reativas para suprir a necessidade de ‘real-time’ de alguns sistemas.
Qual foi a primeira opção? Bom, como trabalhamos com o incrível Framework Laravel, temos disponível integração de forma fácil com algumas soluções. A primeira que veio em mente foi o Pusher, mas nenhum dos planos se encaixou bem no quesito custo benefício.
O site não deixa bem claro sobre as conexões de cada plano, o plano free por exemplo diz que são 100 conexões simultâneas porém, no dashboard a informação exibida é um limite diário de 100 conexões. Fizemos um teste com o plano free e colocamos esse recurso no nosso EAD e em torno de 5 horas excedemos o limite.
Não precisa ser um gênio da matemática para ver que vai sair um pouco caro usar o Pusher como servidor broadcast mas, deixando bem claro que ele é uma ótima ferramenta e pode se encaixar em vários outros cenários.
Todos que já estudaram/trabalharam com Nodejs provavelmente aprenderam a implementar um chat simples utilizando o socket.io.
Utilizando o socket.io juntamente com o Redis podemos construir uma arquitetura descrita no diagrama abaixo:
What, como assim?
Resumindo o Redis é um banco de dados NoSQL bastante usado para cache que possui várias estruturas de dados e outras funcionalidades, uma delas o Pub/Sub.
Utilizando Pub/Sub, quando uma API disparar um evento no sistema ele será publicado em um canal do Redis, nosso servidor broadcast estará inscrito neste canal para ouvir eventos e notificar nossos clientes (browsers) através de WebSockets.
Vamos a um exemplo bem simples!
Primeiro passo criar uma pasta para o projeto e instalar as dependências do servidor.
Depois de instalar dependências entre no seu editor preferido e crie o arquivo server.js com o seguinte código.
E nosso simples server está pronto.
Uma boa prática é criar um comando no package.json para executar o nosso servidor.
Execute no console ‘yarn run dev’ e o server estará em pleno funcionamento.
Nosso server estará ouvindo todas as publicações pois usamos o evento ‘psubscribe’ passando o pattern ‘*’ , não entrarei muito em detalhes do Redis pois estenderia muito o post.
Tá, mas como notificar meus clientes conectados? Até agora estamos ouvindo apenas eventos do nosso banco de dados. Essa parte é bem simples apenas deixe o server.js como a imagem abaixo:
Bom essa é a primeira parte, agora vamos adicionar nesse mesmo projeto um arquivo index.html para simular um cliente conectado, lembrando que o cliente em um caso real seria outro aplicativo. Fiz algumas modificações no arquivo server.js para carregar nosso arquivo index.html e arrumei a ordem de parâmetros do evento pmessage.
Agora criaremos o arquivo index.html que o server esta carregando.
Pronto! Agora temos o cliente conectado e recebendo eventos emitidos do servidor broadcast.
A linha que importa o arquivo socket.io.js funciona por que esse pacote está instalado no nosso servidor.
Mas está faltando algo, vamos relembrar o que fizemos:
- Criamos um servidor que escuta eventos do banco de dados Redis usando Pub/Sub.
- Quando há alguma publicação no Redis nosso server captura e emite uma mensagem usando socket.io assim notificando todos os clientes que estão ouvindo esse canal.
- Simulamos uma aplicações frontend conectada no nosso servidor broadcast, nesse caso adicionamos um arquivo index.html no próprio servidor.
Beleza, mas está faltando nossa aplicação backend que publicará nos canais do Redis, mas como falei ele possui SDKs para diversas linguagens e para não estender mais o assunto vou publicar eventos diretamente no cliente do Redis no console, utilizando um container baixado no Docker Hub.
Depois de me conectar com o Redis via console, envio a mensagem que pode ser um objeto da sua linguagem serializado ou uma string como nesse exemplo, nosso servidor broadcast captura e emite um evento a todos os clientes conectados passando essa mensagem.
E é isso aí, abordei de forma bem simples lembrando que tem toda a parte de segurança desse protocolo e autenticação.
Utilizar algum Framework que auxilie no desenvolvimento desse servidor broadcast é indispensável.
Até a próxima!
Vou deixar os links dos repositórios de uma aplicação que estou criando de atendimento via chat para ser adicionado em websites e vou testar essa ideia.