WebSocket em TypeScript: desenvolvimento avançado de aplicações em tempo real

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

WebSocket em TypeScript: Construindo aplicações avançadas em tempo real

\n\n

As aplicações em tempo real tornaram-se parte essencial da web moderna. De chats e notificações a jogos online e plataformas de negociação — a tecnologia WebSocket fornece uma conexão bidirecional constante entre cliente e servidor. Em um nível avançado, o desenvolvimento de tais sistemas requer não apenas a compreensão do protocolo, mas também a capacidade de construir arquiteturas tolerantes a falhas e escaláveis. Neste artigo, vamos analisar como criar aplicações WebSocket de nível de produção em TypeScript, usando as melhores práticas e padrões.

\n\n

1. Arquitetura e clusterização do servidor WebSocket

\n\n

Um único servidor WebSocket não suportará a carga de um projeto real. A tarefa principal é organizar a clusterização e a troca de mensagens entre as instâncias. Vamos considerar a arquitetura usando a biblioteca ws e o barramento de eventos Redis.

\n\n

Instalaremos as dependências:

\n
npm install ws redis ioredis @types/ws @types/ioredis
\n\n

Criaremos um servidor clusterizado básico:

\n\n
import { WebSocketServer, WebSocket } from 'ws';\nimport Redis from 'ioredis';\n\nconst redisPub = new Redis();\nconst redisSub = new Redis();\n\nconst wss = new WebSocketServer({ port: 8080 });\n\n// Canal para comunicação entre servidores\nconst CHANNEL = 'ws:messages';\n\nredisSub.subscribe(CHANNEL, (err, count) => {\n  if (err) console.error('Erro de inscrição:', err);\n  console.log(`Inscrito em ${count} canais`);\n});\n\n// Recebendo mensagens de outras instâncias\nredisSub.on('message', (channel, message) => {\n  const parsed = JSON.parse(message);\n  wss.clients.forEach((client) => {\n    if (client.readyState === WebSocket.OPEN) {\n      client.send(parsed.data);\n    }\n  });\n});\n\nwss.on('connection', (ws) => {\n  console.log('Nova conexão');\n\n  ws.on('message', (data) => {\n    const message = data.toString();\n    // Publica no Redis para todas as instâncias\n    redisPub.publish(CHANNEL, JSON.stringify({ data: message }));\n  });\n});
\n\n

Vantagens:

\n
    \n
  • Escalabilidade horizontal — adicione quantos servidores quiser
  • \n
  • Tolerância a falhas — se uma instância cair, as outras continuam funcionando
  • \n
  • Barramento de mensagens unificado via Redis Pub/Sub
  • \n
\n\n

2. Autenticação e gerenciamento de sessões

\n\n

Em aplicações de produção, não se pode confiar em conexões não autenticadas. Implementaremos a verificação de tokens via JWT ao estabelecer a conexão.

\n\n

Instalaremos jsonwebtoken:

\n
npm install jsonwebtoken @types/jsonwebtoken
\n\n

Criaremos um middleware para autenticação WebSocket:

\n\n
import { IncomingMessage } from 'http';\nimport jwt from 'jsonwebtoken';\n\nconst JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';\n\ninterface AuthenticatedSocket extends WebSocket {\n  userId?: string;\n}\n\nfunction authenticate(ws: AuthenticatedSocket, req: IncomingMessage): boolean {\n  const url = new URL(req.url || '', 'http://localhost');\n  const token = url.searchParams.get('token');\n\n  if (!token) {\n    ws.close(4001, 'Token não fornecido');\n    return false;\n  }\n\n  try {\n    const decoded = jwt.verify(token, JWT_SECRET) as { userId: string };\n    ws.userId = decoded.userId;\n    console.log(`Usuário ${decoded.userId} autenticado`);\n    return true;\n  } catch (err) {\n    ws.close(4002, 'Token inválido');\n    return false;\n  }\n}\n\n// Uso\nwss.on('connection', (ws: AuthenticatedSocket, req) => {\n  if (!authenticate(ws, req)) return;\n\n  ws.on('message', (data) => {\n    // Agora sabemos o userId\n    console.log(`Mensagem de ${ws.userId}: ${data}`);\n  });\n});
\n\n

Recomendações:

\n
    \n
  • Envie o token via parâmetro de consulta ou cabeçalhos ao estabelecer a conexão
  • \n
  • Use tokens de acesso de curta duração e tokens de atualização
  • \n
  • Armazene sessões no Redis

Blogs

Book Recommendations