🚀 Projeto: Nginx com Balanceamento de Carga e Visualização em Tempo Real
🎯 Objetivo
Criar um ambiente que simula um sistema web real, demonstrando visualmente como o Nginx atua como um Reverse Proxy (Proxy Reverso) e distribui a carga (Load Balancing) entre duas APIs de backend idênticas.
🛠️ Tecnologias Utilizadas
- Docker & Docker Compose: Para criar e gerenciar os contêineres dos nossos serviços.
- Nginx: Nosso proxy reverso e balanceador de carga.
- Node.js (Express): Para criar duas APIs de backend.
- k6: Uma ferramenta moderna para teste de carga.
- HTML/JS (com Chart.js): Para criar um dashboard de visualização em tempo real.
📁 Parte 1: Estrutura do Projeto
Garanta que seu projeto tenha a seguinte estrutura de pastas e arquivos:
projeto-nginx-visual/
├── api-01/
│ ├── index.js
│ ├── package.json
│ └── Dockerfile
├── api-02/
│ ├── index.js
│ ├── package.json
│ └── Dockerfile
├── nginx/
│ ├── nginx.conf
│ └── Dockerfile
├── visualizer/
│ ├── index.html
│ └── chart.js
├── docker-compose.yml
└── load-test.js
⚙️ Parte 2: Criando as APIs de Backend (Node.js)
1. Arquivos da api-01/
api-01/package.json:{ "name": "api-01", "version": "1.0.0", "main": "index.js", "scripts": { "start": "node index.js" }, "dependencies": { "express": "^4.18.2" } }api-01/index.js(Corrigido para responder na rota raiz):const express = require('express'); const app = express(); const PORT = 3000; const SERVER_ID = "API-01"; app.get('/', (req, res) => { console.log(`[${SERVER_ID}] Recebeu requisição`); res.json({ servidor: SERVER_ID, timestamp: new Date().toISOString() }); }); app.listen(PORT, () => console.log(`[${SERVER_ID}] Rodando na porta ${PORT}`));api-01/Dockerfile(Corrigido para o contexto de build correto):FROM node:18-alpine WORKDIR /usr/src/app # Copia APENAS os arquivos necessários da API-01 COPY ./api-01/package.json ./ COPY ./api-01/index.js ./ RUN npm install EXPOSE 3000 CMD [ "npm", "start" ]
2. Arquivos da api-02/
Copie os arquivos da api-01/ para api-02/ e mude APENAS UMA LINHA no api-02/index.js e o Dockerfile para refletir a api-02.
api-02/index.js(linha 5):const SERVER_ID = "API-02"; // Mude de API-01 para API-02api-02/Dockerfile:FROM node:18-alpine WORKDIR /usr/src/app # Copia APENAS os arquivos necessários da API-02 COPY ./api-02/package.json ./ COPY ./api-02/index.js ./ RUN npm install EXPOSE 3000 CMD [ "npm", "start" ]
proxy Parte 3: Configurando o Nginx
nginx/nginx.conf(Simplificado para HTTP):events { } http { # Define o grupo de servidores de backend (Load Balancing) upstream backend_servers { server api-01:3000; server api-02:3000; } # Servidor principal (HTTP) server { listen 80; server_name localhost; # Rota para o Dashboard de Visualização location / { root /usr/share/nginx/html; index index.html; } # Rota da API (Proxy Reverso) location /api { # Remove o /api antes de enviar para o backend rewrite /api(.*) /$1 break; # Envia a requisição para o grupo de servidores proxy_pass http://backend_servers; # Cabeçalhos importantes para o proxy proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } }nginx/Dockerfile(Corrigido para o contexto de build correto):FROM nginx:1.23-alpine # Copia nossa configuração personalizada (relativo ao 'context') COPY ./nginx/nginx.conf /etc/nginx/nginx.conf # Copia os arquivos do visualizer (relativo ao 'context') COPY ./visualizer /usr/share/nginx/html
📊 Parte 4: Criando o Dashboard de Visualização
-
Obtenha o Chart.js (Versão Correta): Crie o arquivo
visualizer/chart.js. Abra o link abaixo, copie todo o conteúdo e cole no seu arquivochart.js.- Link:
https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.min.js
- Link:
-
visualizer/index.html:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Visualizador de Carga Nginx</title> <script src="chart.js"></script> <style> body { font-family: sans-serif; display: grid; place-items: center; background: #f4f4f4; } #chart-container { width: 500px; } h1 { color: #333; } h2 { margin: 5px 0; } #api-01 { color: #36A2EB; } #api-02 { color: #FF6384; } </style> </head> <body> <h1>Dashboard de Balanceamento de Carga</h1> <div id="chart-container"> <canvas id="loadChart"></canvas> </div> <h2 id="api-01">API-01: 0</h2> <h2 id="api-02">API-02: 0</h2> <h3>Total: <span id="total">0</span></h3> <script> const ctx = document.getElementById('loadChart').getContext('2d'); const counters = { 'API-01': 0, 'API-02': 0 }; let total = 0; const h2_api1 = document.getElementById('api-01'); const h2_api2 = document.getElementById('api-02'); const span_total = document.getElementById('total'); const loadChart = new Chart(ctx, { type: 'pie', data: { labels: ['API-01', 'API-02'], datasets: [{ data: [0, 0], backgroundColor: ['#36A2EB', '#FF6384'] }] }, options: { responsive: true, animation: { duration: 500 } } }); async function fetchData() { try { const response = await fetch('/api'); if (!response.ok) throw new Error('Falha na rede'); const data = await response.json(); counters[data.servidor]++; total++; h2_api1.innerText = `API-01: ${counters['API-01']}`; h2_api2.innerText = `API-02: ${counters['API-02']}`; span_total.innerText = total; loadChart.data.datasets[0].data = [counters['API-01'], counters['API-02']]; loadChart.update(); } catch (error) { console.error('Erro ao buscar API:', error); } } setInterval(fetchData, 200); </script> </body> </html>
🐳 Parte 5: Orquestrando com Docker Compose
docker-compose.yml(Corrigido para usarcontextedockerfile):services: api-01: build: context: . dockerfile: ./api-01/Dockerfile api-02: build: context: . dockerfile: ./api-02/Dockerfile nginx: build: context: . dockerfile: ./nginx/Dockerfile ports: - "80:80" depends_on: - api-01 - api-02
⚡ Parte 6: Script de Teste de Carga (k6)
load-test.js(Simplificado para HTTP):import http from 'k6/http'; import { sleep } from 'k6'; export const options = { stages: [ { duration: '30s', target: 10 }, // Simula 10 usuários por 30 segundos ], }; export default function () { // Acessa o endpoint da API através do Nginx http.get('http://localhost/api'); sleep(0.5); // Espera 500ms entre requisições }
🏁 Parte 7: Executando o Projeto!
1. Instale o k6: Siga as instruções em k6.io para o seu sistema operacional.
2. Suba os Serviços: No terminal, na raiz do projeto, execute:
docker-compose up --build
Isso irá construir as imagens e iniciar os 3 contêineres (api-01, api-02, nginx).
3. Acesse o Visualizador:
Abra seu navegador e vá para: http://localhost
Você verá o dashboard. Ele já começará a fazer requisições lentamente, e o gráfico de pizza deve mostrar uma divisão de ~50% para cada API.
4. Execute o Teste de Carga:
K6 Load Testing for API on Windows 11 🚀
K6 é uma poderosa ferramenta open-source para testes de carga de APIs. Abaixo estão os passos para configurar e executar o K6 no Windows 11.
1. Instalar o K6 no Windows 11 🖥️
-
Abra um terminal (Prompt de Comando, PowerShell ou Bash).
-
Use o Gerenciador de Pacotes do Windows (Winget) para instalar o K6:
winget install k6 --source winget
Em outro terminal, execute o k6:
k6 run load-test.js
5. Observe o Dashboard: Volte para o navegador. Você verá os números no dashboard subindo drasticamente rápido. O gráfico de pizza se ajustará em tempo real, mas deve sempre se manter próximo de 50/50, provando que o Nginx está distribuindo a carga.
6. Para Desligar:
Pressione Ctrl + C no terminal onde o docker-compose está rodando e depois execute:
docker-compose down