Leodario.com

Leodario.com – Tudo sobre Tecnologia

Aula 69 – API JavaScript, Node.js e Express – Rate Limiting Advanced – Sliding window, token bucket

Imagem destacada da aula de API

Introdução (3 min)

Imagine um restaurante com capacidade limitada. Para evitar superlotação e garantir um bom atendimento, o restaurante limita o número de clientes que podem entrar em determinado período. Este controle de fluxo é análogo ao Rate Limiting, uma técnica essencial para proteger e otimizar APIs modernas.

Rate Limiting é estratégico para prevenir abusos, como ataques de negação de serviço (DoS), garantir a disponibilidade do serviço para todos os usuários e gerenciar os recursos de infraestrutura de forma eficiente. Nesta aula, vamos aplicar o Rate Limiting com as estratégias Sliding Window e Token Bucket, utilizando Node.js e Express.

No contexto Node.js/Express, o Rate Limiting é implementado através de middlewares que interceptam as requisições e aplicam as regras de limitação definidas.

Conceito Fundamental (7 min)

Rate Limiting restringe o número de requisições que um cliente pode fazer a uma API em um determinado período. Sliding Window e Token Bucket são algoritmos para implementar esse controle. Sliding Window divide o tempo em janelas e conta as requisições dentro de cada janela. Já o Token Bucket imagina um balde que recebe tokens a uma taxa constante; cada requisição consome um token, e se não houver tokens disponíveis, a requisição é rejeitada.

Em produção, o Rate Limiting é usado em APIs de redes sociais, plataformas de e-commerce, serviços financeiros, entre outros. Integra-se com tecnologias como caches, balanceadores de carga e bancos de dados para garantir a alta disponibilidade e performance.

Vantagens do Rate Limiting incluem: proteção contra DoS, melhor gerenciamento de recursos, controle de custos e garantia de QoS (Quality of Service). Como desvantagem, uma configuração inadequada pode prejudicar a experiência do usuário legítimo.

Implementação Prática (10 min)

const express = require('express');
const app = express();

// Middleware Sliding Window simplificado (para fins didáticos) const slidingWindow = (req, res, next) => { const windowSize = 60000; // 1 minuto em milissegundos const maxRequests = 10; let requests = 0; // Simulação em memória (em produção, usar Redis ou similar)

if (requests >= maxRequests) { return res.status(429).send('Too Many Requests'); }

requests++; setTimeout(() => requests--, windowSize); // Decrementar após a janela

next(); };

// Middleware Token Bucket simplificado (para fins didáticos) const tokenBucket = (req, res, next) => { const bucketSize = 10; const refillRate = 1; // 1 token por segundo let tokens = bucketSize;

if (tokens <= 0) { return res.status(429).send('Too Many Requests'); }

tokens--; setInterval(() => { if (tokens < bucketSize) { tokens += refillRate; // Adicionar tokens à taxa definida } }, 1000); // Intervalo de 1 segundo

next(); };

app.get('/sliding', slidingWindow, (req, res) => { res.send('Sliding Window'); });

app.get('/token', tokenBucket, (req, res) => { res.send('Token Bucket'); });

app.listen(3000, () => console.log('Servidor rodando na porta 3000'));

npm install express
node index.js

Este código demonstra implementações básicas de Sliding Window e Token Bucket. Em um ambiente de produção, utilize bibliotecas especializadas como o express-rate-limit para uma solução mais robusta e eficiente. Configurar o express-rate-limit para HostGator Plano M é similar a outros planos, respeitando os limites de recursos.

Exercício Hands-On (5 min)

Desafio: Modifique o código para persistir os dados de Rate Limiting utilizando um armazenamento em memória como o node-cache. Implemente logging usando o console.log para registrar cada requisição e o estado do limitador. Teste a solução fazendo várias requisições em um curto período de tempo.

Solução (fragmento com node-cache):

const NodeCache = require( "node-cache" );
const myCache = new NodeCache();

// ... dentro do middleware let requests = myCache.get("requests") || 0; // ... (resto do código) myCache.set("requests", requests);

Validação: Verifique se as requisições são limitadas após atingir o limite definido. Observe o log para acompanhar o estado do limitador.

Troubleshooting: Certifique-se de que o node-cache está instalado (npm install node-cache). Verifique a lógica do seu código para garantir que as variáveis estão sendo atualizadas corretamente.

Próximos Passos: Explore bibliotecas de Rate Limiting mais avançadas e configure-as para diferentes cenários e estratégias de limitação.

🚀 Pronto para a próxima aula?

Continue sua jornada no desenvolvimento de APIs e domine Node.js & Express!

📚 Ver todas as aulas