📚 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 catalogo_projetos/infra_nginx_02_spring


🏛️ Arquitetura Visual & Engenharia de Infraestrutura

O diagrama abaixo ilustra a topologia de componentes, balanceamento, esteiras de automação e observabilidade na subpasta api-spring/:

Arquitetura de Infraestrutura

flowchart TD
    subgraph Config["Configuração & IaC"]
        C1["Manifestos Declarativos"] --> C2["Variáveis & Segredos"]
    end
    subgraph Orquestracao["Orquestração & Redes"]
        O1["Load Balancer / Ingress"] --> O2["Pods / Contêineres de Serviço"]
    end
    subgraph Observabilidade["Observabilidade & Segurança"]
        M1["Telemetria Prometheus / k6"] --> M2["Scanners SAST & Dashboards"]
    end
    subgraph Qualidade["Homologação & Qualidade"]
        Q1["Automação CI/CD"] --> Q2["Checkpoints CP-01..05 PASS"]
    end

    Config --> Orquestracao
    Orquestracao --> Observabilidade
    Observabilidade --> Qualidade

    style Config fill:#e3f2fd,stroke:#1976d2,stroke-width:1.5px
    style Orquestracao fill:#fffde7,stroke:#fbc02d,stroke-width:1.5px
    style Observabilidade fill:#e8f5e9,stroke:#388e3c,stroke-width:1.5px
    style Qualidade fill:#f3e5f5,stroke:#7b1fa2,stroke-width:1.5px

🎯 Engenharia de Requisitos & Modelagem Formal

👤 User Stories (Histórias de Usuário)

ID Persona História de Usuário Critério de Aceite Prioridade
US-01 Arquiteto Java Desejo balancear microsserviços Spring Boot 3 com Nginx Least Connections Roteamento inteligente enviando requisições ao nó com menor número de conexões ativas Alta
US-02 Engenheiro de Confiabilidade Desejo integração com Spring Boot Actuator /health no balanceador Monitoramento contínuo de integridade através de endpoint padrão corporativo Alta
US-03 Desenvolvedor Backend Desejo balanceamento com ponderação de pesos (weights) por hardware Capacidade de atribuir pesos diferentes para nós de capacidades distintas Alta
US-04 Operador de TI Desejo container multi-stage build empacotando jar enxuto do Spring Dockerfile otimizado em camadas com Eclipse Temurin Java 21 Média
US-05 Auditor de Disponibilidade Desejo testes comprovando zero downtime durante reinício de nós Bateria de testes de carga simulando restart rotativo de instâncias Média

⚙️ Requisitos Funcionais (RF)

ID Descrição do Requisito Criticidade
RF-01 Algoritmo Least Connections e ponderação por pesos (weight) no Nginx Alta
RF-02 Microsserviço Spring Boot 3 com endpoints REST e Actuator /health Alta
RF-03 Orquestração multi-contêiner com health checks configurados no compose Alta
RF-04 Painel visual de status dos contêineres e tráfego em tempo real Média
RF-05 Módulo de testes automatizados com simulação de carga contínua Média

🛡️ Requisitos Não-Funcionais (RNF)

ID Especificação Arquitetural Criticidade
RNF-01 Suporte a tráfego concorrente elevado com pool de conexões otimizado Alta
RNF-02 Garantia de inicialização em menos de 15 segundos por réplica Java Média
RNF-03 Isolamento de dependências com código fonte Java na pasta api-spring/ Alta
RNF-04 Conformidade com padrões corporativos Spring Boot e Java 21 LTS Alta
RNF-05 Artefatos de infraestrutura segregados na pasta nginx/ Alta

🔗 Matriz de Rastreabilidade (RTM)

User Story Requisito Funcional Requisito Não-Funcional Módulo / Artefato de Código Status de Homologação
US-01 RF-01 RNF-01, RNF-05 nginx/nginx.conf Testado
US-02 RF-02 RNF-01, RNF-04 api-spring/src/ Testado
US-03 RF-01 RNF-01, RNF-05 nginx/nginx.conf Testado
US-04 RF-03 RNF-02, RNF-03 api-spring/Dockerfile Testado
US-05 RF-05 RNF-01, RNF-04 tests/load_test.sh Testado

🏁 Checkpoints de Qualidade & Homologação

Checkpoint Escopo da Validação Artefato Verificado Status
CP-01 Configuração Declarativa do Ambiente api-spring/ PASS ✅
CP-02 Provisionamento & Orquestração Deployments / Services PASS ✅
CP-03 Redes, Proxies & Segurança de Borda Ingress / Security Groups PASS ✅
CP-04 Observabilidade, Métricas & SAST Metrics / Scanners PASS ✅
CP-05 Homologação com Suíte de Testes Test Suite / CI Gate PASS ✅