📚 Pré-requisitos Teóricos: este projeto aplica conceitos ensinados em Cap. 09 (Nginx) do Guia de Redes. Recomendado revisar antes de começar.

🚀 Projeto: Nginx com Balanceamento de Carga (Java 21 / Spring Boot)`

🎯 Objetivo

Criar um ambiente que simula um sistema web real, demonstrando visualmente como o Nginx atua como um Reverse Proxy e distribui a carga (Load Balancing) entre duas instâncias idênticas de uma API Spring Boot.

Este projeto é a versão em Java/Spring Boot do mesmo experimento feito com Node.js em infra_nginx_01_nodejs — a diferença central é que aqui as duas instâncias de backend rodam a partir do mesmo .jar, diferenciadas apenas por uma variável de ambiente (SERVER_ID), em vez de serem dois projetos separados.`

🏗️ Arquitetura do Sistema

graph TD
    subgraph "Cliente"
        User["Navegador (Browser)"]
    end

    subgraph "Docker Compose Network"
        Nginx["Nginx (Load Balancer & Proxy Reverso)"]
        API_01["api-01 (Spring Boot, SERVER_ID=API-01)"]
        API_02["api-02 (Spring Boot, SERVER_ID=API-02)"]
        Visualizer["Visualizador (Static Files)"]
    end

    User -->|":80 /"| Nginx
    Nginx -->|"/api (Load Balancing)"| API_01
    Nginx -->|"/api (Load Balancing)"| API_02
    Nginx -->|"Server Files"| Visualizer
    Visualizer -->|"fetch('/api')"| Nginx

🛠️ Tecnologias Utilizadas

—`

📁 Parte 1: Estrutura do Projeto

infra_nginx_02_spring/
├── src/main/java/br/com/tarefas/load_balancing_01/
│   ├── ApiController.java
│   └── LoadBalancing01Application.java
├── src/main/resources/application.properties
├── pom.xml
├── Dockerfile
├── nginx/
│   ├── nginx.conf
│   └── Dockerfile
├── visualizer/
│   └── index.html
└── docker-compose.yml

—`

⚙️ Parte 2: A API de Backend (Spring Boot)

Ao contrário da versão Node.js (dois projetos api-01/api-02), aqui existe um único projeto Spring Boot. As duas “instâncias” no Docker Compose sobem a mesma imagem, cada uma com um valor diferente de SERVER_ID injetado via variável de ambiente.

—`

🐋 Parte 3: Dockerfile da API (multi-stage build)

# Estágio 1: Build (Compilação)
FROM maven:3.9-eclipse-temurin-21 AS build
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests

# Estágio 2: Run (Execução)
FROM eclipse-temurin:21-jre-jammy
WORKDIR /app
COPY --from=build /app/target/*.jar app.jar
EXPOSE 8080
# A variável SERVER_ID será injetada pelo Docker Compose
ENTRYPOINT ["java", "-jar", "app.jar"]

—`

Parte 4: Configurando o Nginx

nginx/nginx.conf:

upstream backend_servers {
    # O padrão é round-robin (alterna entre eles)
    # Note a porta 8080, padrão do Spring Boot
    server api-01:8080;
    server api-02:8080;
}

events { }

http {
    server {
        listen 80;
        server_name localhost;

        location / {
            root /usr/share/nginx/html;
            index index.html;
        }

        location /api {
            rewrite /api(.*) /$1 break;
            proxy_pass http://backend_servers;

            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:

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 5: Dashboard de Visualização

visualizer/index.html consome fetch('/api') a cada 200ms e monta um gráfico de pizza (Chart.js via CDN) com a contagem de respostas de cada SERVER_ID, igual ao dashboard de infra_nginx_01_nodejs — o payload JSON (servidor/timestamp) é o mesmo formato, então o mesmo dashboard funciona sem alteração.

—`

🐳 Parte 6: Orquestrando com Docker Compose

services:
  api-01:
    build:
      context: .
      dockerfile: ./Dockerfile
    environment:
      - SERVER_ID=API-01

  api-02:
    build:
      context: .
      dockerfile: ./Dockerfile
    environment:
      - SERVER_ID=API-02

  nginx:
    build:
      context: .
      dockerfile: ./nginx/Dockerfile
    ports:
      - "80:80"
    depends_on:
      - api-01
      - api-02

Note que api-01 e api-02 usam o mesmo Dockerfile/contexto — a diferença entre eles é só a variável de ambiente SERVER_ID.

—`

🏁 Parte 7: Executando o Projeto!

1. Suba os serviços:

docker-compose up --build

Isso constrói a imagem Spring Boot (usada duas vezes, para api-01 e api-02) e a imagem do Nginx.

2. Acesse o Visualizador: Abra http://localhost. O dashboard começa a fazer requisições automaticamente e o gráfico de pizza deve convergir para ~50%/50% entre API-01 e API-02.

3. (Opcional) Teste de carga com k6: Reaproveite o load-test.js de infra_nginx_01_nodejs apontando para http://localhost/api — a rota é idêntica.

4. Para desligar:

docker-compose down

Voltar para Projetos

—`

🚀 Como Executar no Laboratório

1. Abra o terminal na pasta deste projeto

No seu editor/IDE, abra a pasta deste projeto (File > Open Folder) ou navegue via terminal:

cd infra_nginx_02_spring

2. Execute a aplicação ou testes

terraform init && terraform plan
# ou docker-compose up -d

[!TIP] Dica para execução a partir da raiz do repositório: Se você abriu o repositório completo no VS Code, basta navegar até a pasta antes de executar: cd proj_aplicacoes_full_stack/projetos/infra_nginx_02_spring