/projects/dietbox-socket
← Todos os projetosDietbox Socket
Atualizações ao vivo como serviço próprio, para subirem no próprio relógio.
Engenheiro de Software Sênior · 2022
Visão geral
Trinta e quatro commits em dois meses de 2022, para um serviço que sobreviveu a ambos: um servidor de tempo real que mantém cada conexão aberta, junta cada cliente a uma sala com o nome do seu id de usuário, e expõe um único endpoint para onde o resto da plataforma posta quando algo precisa ser empurrado. Ele fica fora do produto porque uma conexão de longa duração e uma requisição não são o mesmo tipo de tráfego.
O que eu fiz
Praticamente uma construção solo: trinta e três dos trinta e quatro commits, do handshake ao harness de carga que comprovou que ele aguentava.
- O próprio servidor de tempo real: o handshake com segredo compartilhado, a atribuição de sala por id de usuário, e a desconexão imediata de um cliente que acaba sem entrar em nenhuma sala.
- O endpoint de notificação para onde o resto da plataforma posta, e os endpoints de info e de saúde usados para observar o próprio serviço.
- A convenção de carregamento de handlers: um handler de evento é um arquivo, carregado automaticamente a partir de um diretório.
- O harness de teste de carga, construído para manter deliberadamente uma parte dos clientes em long-polling em vez de deixar todos fazerem upgrade.
O problema
O monolito subia uma vez por madrugada, e qualquer coisa que compartilhasse seu pipeline compartilhava seu ritmo — um canal de tempo real que só pode mudar às três da manhã é um canal de tempo real que ninguém muda. Separadamente, conexões abertas e tráfego de requisição não querem a mesma quantidade de instâncias: uma escala com quantas pessoas estão online, a outra com quantas requisições chegam.
Arquitetura
A plataforma posta uma sala, um nome de evento e um payload para o endpoint de notificação; o servidor resolve quem está naquela sala agora e empurra o evento diretamente para eles.
- PlatformOutro serviço da plataforma posta uma sala, um nome de evento e um payload para o endpoint de notificação.
- Room resolvedO servidor verifica quais conexões estão de fato naquela sala agora.
- Fan-outO evento é empurrado para cada cliente atualmente na sala.
- BrowserO cliente recebe o evento e atualiza sem um refresh.
O que faz
- O endpoint de notificação para onde o resto da plataforma posta quando algo precisa ser empurrado.
- Um endpoint de info que reporta a contagem de conexões ao vivo, para monitoramento.
- Um endpoint de saúde que reporta a própria latência.
- Um handshake com segredo compartilhado que desconecta um cliente imediatamente se ele acabar sem entrar em nenhuma sala.
Decisões de engenharia
Tempo real como implantação própria
Dois motivos, ambos reais: conexões abertas e tráfego de requisição escalam em eixos diferentes, e o produto subia uma vez por madrugada — um canal que só pode mudar às três da manhã é um canal que ninguém muda. Separá-lo em um serviço próprio deixou cada eixo escalar nos seus próprios termos, e deixou este subir no próprio relógio.
Uma sala por id de usuário
O endereçamento é por identidade, não por conexão, então a plataforma consegue empurrar para uma pessoa sem saber quantas abas, dispositivos ou reconexões essa pessoa tem abertos no momento.
Handlers carregados automaticamente de um diretório
Adicionar um evento é adicionar um arquivo — não existe registro para lembrar de atualizar, nem handler que existe no código mas nunca foi ligado.
Um teste de carga que mantém clientes em long-polling
Nem todo cliente faz upgrade para um websocket. Um teste de carga em que todos fazem mede uma população que não existe, então o harness mantém deliberadamente uma parte dos clientes em long-polling via HTTP.