Executando verificação de segurança...
5

Como uma 'simples' tarefa me fez aprender três coisas novas.

Decidi ajudar um amigo em seu projeto pessoal. Ele estava enfrentando um grande problema para manter as notificações no sistema usando websockets. O backend (API) estava escalonado horizontalmente usando clustering do Node.js. Sempre que a conexão do websocket caía, ele automaticamente tentava se reconectar, mas aí estava o problema: dificilmente ele apontava para o mesmo cluster em que a instância da conexão existia, resultando na falta de emissão de muitas notificações para o cliente.

As notificações são utilizadas para retornar o status do processo e sua porcentagem de conclusão. Eu realmente não fazia ideia de como resolver esse problema, mas bati no peito e disse 'eu consigo'. Comecei a pesquisar e descobrir diversos tópicos que me ajudariam, como Sticky Sessions (sessões persistentes), mas não entrava na minha cabeça de jeito nenhum. Eu precisava de uma solução a nível de código, sem mexer no nginx. Comecei a ler a documentação do Node.js e a entender como o clustering funciona, e isso foi uma salvação para mim. Ele basicamente faz um clone da aplicação para cada núcleo do seu processador. Por exemplo, se eu tenho 8 núcleos, 8 processos filhos serão criados para executar minha aplicação em cada um (observação: rodando na mesma porta). Esses clusters são gerenciados pelo cluster master. Quanto mais eu me aprofundava na documentação, mais eu sabia que era possível fazer isso de uma forma simples e que não ficasse complexa para quem fosse ler depois.

Lógica: Todo cluster possui um identificador (id), e sempre que o cliente solicita a conexão do websocket, eu precisava saber em qual cluster minha instância de conexão estava. Então, ficou assim: quando a conexão era efetuada, o servidor já retornava o identificador do cluster. Eu apenas precisava, de alguma forma, informar esse cluster-id para o servidor a cada requisição para a API. A maneira mais correta que surgiu na minha cabeça foi alterar o interceptor já existente e adicionar mais um cabeçalho 'cluster-id'. Só que aí surgiu o segundo problema: o valor nunca chegava no backend, e eu ficava me perguntando (inclusive para o GPT) por que o cabeçalho não estava sendo enviado na requisição. Descobri que é necessário informar os cabeçalhos que são permitidos na requisição utilizando 'Access-Control-Allow-Headers'.

Agora, com a informação do 'cluster-id' chegando, eu precisava fazer com que o cluster correto enviasse a resposta para o cliente. Até que foi fácil: o cluster master tem acesso a todos os processos filhos. A cada requisição, eu precisava mandar uma mensagem para o master, que então a encaminhava para o filho correto. A partir daí, o filho notificava o cliente.

Mas e a terceira coisa?

O clustering é uma salvação no backend, né? Comecei a me perguntar, será que existe algo parecido no frontend? Depois de algumas pesquisas, descobri a existência de web workers, onde basicamente definimos uma thread separada no navegador para executar sub-rotinas pesadas, como calcular e ler arquivos gigantes!

Como você resolveria esse problema ?