Pular para conteúdo

a. Visão geral

Neste lab

  • Instalar e verificar as ferramentas usadas em todos os labs: Docker + Compose, JDK 21, Maven, uv + Python 3.12, k6, kubectl, kind ou minikube, Git.
  • Criar o seu repositório BoxOffice com a estrutura que os próximos doze labs vão preencher.
  • Conhecer os nomes de serviços, portas, variáveis de ambiente e convenções que todos os labs compartilham.
  • Medir a sua máquina pela primeira vez: quantas requisições por segundo ela atende, e com que latência?

Durante o semestre você vai construir o BoxOffice, uma plataforma de venda de ingressos para shows, jogos e festivais. Ele começa como um pequeno serviço no seu notebook e cresce, lab após lab, até virar um sistema com proxy de borda, API gateway, cache, banco replicado, stream de eventos, observabilidade, Kubernetes e um assistente de IA. Cada lab acrescenta um componente da paleta do System Design Playground, e cada lab termina com uma medição: projeto de sistemas é feito de trade-offs, e um trade-off só é real quando você consegue colocar um número nele.

Este primeiro lab é curto, mas importante: um ambiente quebrado custa horas depois, no meio de um teste de carga.

Antes de começar

Tempo 1–2 horas (a maior parte são downloads)
Você precisa de um computador com 8 GB de RAM ou mais (16 GB é confortável a partir do lab 4), ~20 GB livres em disco, direitos de administrador, acesso à internet
Sistema operacional macOS, Linux ou Windows 10/11 (todo comando da disciplina roda em um shell Bash)
Estado inicial nenhum: este lab cria o repositório boxoffice/ a partir de uma pasta vazia

Primeiro lab

Não há nada para recuperar: todo lab seguinte começa do estado ao fim do anterior, e cada página de lab oferece um boxoffice-after-lab-<n>.zip pronto se você pular ou quebrar um lab.

Slides

Clique nos slides e use ← → para navegar; F abre em tela cheia e P abre a visão do apresentador, com as notas. Abrir os slides em uma nova aba

Aonde vamos chegar

O diagrama mostra o BoxOffice no fim do semestre. Não se preocupe com os detalhes: cada caixa tem o seu lab, e o número em cada rótulo diz qual.

flowchart LR
    user([Fã / k6]) --> edge["edge<br/>Nginx · lab 3"]
    edge --> gw["gateway<br/>lab 4"]
    gw --> auth["auth<br/>lab 4"]
    gw --> catalog["catalog ×3<br/>lab 1"]
    gw --> inventory["inventory<br/>lab 6"]
    gw --> order["order<br/>lab 7"]
    gw --> assistant["assistant<br/>lab 12"]
    catalog --> redis[("redis<br/>lab 5")]
    catalog --> db[("db<br/>PostgreSQL")]
    inventory --> pgb["pgbouncer<br/>lab 6"] --> db
    inventory --> replica[("db-replica<br/>lab 6")]
    order --> kafka[["kafka<br/>lab 7"]]
    kafka --> notification["notification<br/>lab 7"]
    order --> payment["payment<br/>lab 9"]

Conexão com a teoria

Na história da disciplina, este lab abre o capítulo 1: antes de qualquer design, um número — quantas requisições por segundo a sua máquina atende, o primeiro dos requisitos mensuráveis que todo lab seguinte confere.

Este lab acompanha a aula 1, O que é projeto de sistemas: a jornada de escala do BoxOffice, de um servidor a milhões de usuários, é exatamente o caminho que os labs seguem. A etapa "Meça" no fim se conecta com a aula 2, Estimativas.

Serviços e portas do BoxOffice

Todos os labs — e todos os projetos em equipe — usam os nomes abaixo. Não os renomeie: os arquivos de configuração, os scripts k6 e os próximos labs dependem deles. Um serviço escuta na mesma porta dentro do container e na sua máquina, então http://catalog:8082 (a partir de outro container) e http://localhost:8082 (a partir do seu terminal) chegam ao mesmo serviço.

Serviços de aplicação (uma pasta cada em services/):

Serviço no Compose Lab Stack Porta Prefixo público de rota Schema no BD Papel
edge 3 Nginx 1.30 80 — — proxy reverso, balanceador de carga, rate limiting: a única entrada pública a partir do lab 3
gateway 4 Spring Cloud Gateway 8080 todos — roteamento, validação de JWT, cabeçalhos de identidade
auth 4 Spring Boot 8081 /auth/** auth usuários, login, emite JWTs (RS256) e publica o JWKS
catalog 1 Spring Boot 8082 /catalog/** catalog eventos e locais (muita leitura). Roda como catalog-1, catalog-2, catalog-3 a partir do lab 3
inventory 6 Spring Boot 8083 /inventory/** inventory assentos e reservas (fortemente consistente)
order 7 Spring Boot 8084 /orders/** orders pedidos, transactional outbox
payment 9 Spring Boot 8085 /payments/** payment adaptador para o provedor externo de pagamento
notification 7 Spring Boot 8086 /notifications/** notification e-mail/push, consumidor idempotente
search — (opcional) 8087 /search/** — reservado para o projeto
assistant 12 Python 3.12 + FastAPI 8088 /assistant/** assistant assistente de suporte com IA (RAG + ferramentas)

Infraestrutura (imagens oficiais, configuração em infra/):

Serviço no Compose Lab Imagem Porta(s) na sua máquina Observações
db 1 postgres:17 5432 banco boxoffice, usuário boxoffice, senha boxoffice; um schema por serviço
db-replica 6 postgres:17 5433 réplica por streaming do db, somente leitura
pgbouncer 6 edoburu/pgbouncer:v1.26.0-p0 6432 pool de conexões na frente do db
redis 5 redis:8-alpine 6379 cache (maxmemory + LRU)
kafka 7 Apache Kafka (KRaft) 9092 stream de eventos
otel-lgtm 8 grafana/otel-lgtm 3000 (Grafana), 4317/4318 (OTLP gRPC/HTTP) métricas, logs, traces
toxiproxy 9 ghcr.io/shopify/toxiproxy 8474 (API) injeção de latência e falhas
ollama 12 ollama/ollama 11434 LLM local
painel web do k6 2 — 5665 K6_WEB_DASHBOARD=true k6 run …
hello (só no lab 0) 0 nginx:1.30-alpine 8888 alvo da medição de referência

Convenções compartilhadas por todos os serviços:

Tema Convenção
Java JDK 21, Spring Boot 4.1.x (Spring Framework 7, Jackson 3), Spring Cloud 2025.1.x, Maven, sem Lombok (records do Java para os DTOs)
Python Python 3.12 gerenciado pelo uv (uv init, uv add <pacote>, uv run <cmd>, uvx <ferramenta>); nunca pip/venv. Dockerfiles copiam o uv com COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ e rodam uv sync --frozen
Pacotes boxoffice.<serviço> (ex.: boxoffice.catalog); groupId Maven boxoffice, artifactId = nome do serviço
Caminhos HTTP cada serviço atende apenas sob o seu prefixo (catalog → /catalog/...), então o edge e o gateway roteiam sem reescrever caminhos
Banco de dados uma instância PostgreSQL (db), um schema por serviço, de propriedade das migrations Flyway daquele serviço (src/main/resources/db/migration); nada de joins entre schemas
Saúde Spring Boot Actuator: /actuator/health, /actuator/health/liveness, /actuator/health/readiness, /actuator/metrics
Erros RFC 9457 application/problem+json (spring.mvc.problemdetails.enabled: true)
Arquivo Compose docker-compose.yaml na raiz do repositório, nome de projeto boxoffice
Scripts de carga load/*.js (k6), URL base em BASE_URL; resultados salvos em results/

Variáveis de ambiente (o mesmo nome em todo lugar; padrões entre parênteses):

Variável Usada por Significado
DB_HOST (db), DB_PORT (5432), DB_NAME (boxoffice), DB_USER (boxoffice), DB_PASSWORD (boxoffice) todo serviço com banco conexão com o PostgreSQL
DB_REPLICA_HOST (db-replica), DB_REPLICA_PORT (5432) inventory (lab 6) réplica de leitura
REDIS_HOST (redis), REDIS_PORT (6379) catalog (lab 5) cache
AUTH_JWKS_URI (http://auth:8081/auth/.well-known/jwks.json) gateway chaves públicas usadas para validar JWTs
JWT_ISSUER (boxoffice-auth), JWT_TTL (PT1H) auth, gateway emissor e validade do token
ADMIN_EMAIL (admin@boxoffice.dev), ADMIN_PASSWORD (boxoffice-admin) auth administrador criado na inicialização
CATALOG_URL, INVENTORY_URL, ORDER_URL, PAYMENT_URL (http://<serviço>:<porta>) chamadas entre serviços URL base de outro serviço
KAFKA_BOOTSTRAP_SERVERS (kafka:9092) labs 7+ brokers Kafka
OTEL_EXPORTER_OTLP_ENDPOINT (http://otel-lgtm:4318) labs 8+ exportação de telemetria
BASE_URL scripts k6 http://localhost:8082 nos labs 1–2, http://localhost (o edge) a partir do lab 3

Cabeçalhos que atravessam fronteiras entre serviços:

Cabeçalho Quem define Significado
Authorization: Bearer <jwt> cliente identidade, validada pelo gateway
X-User-Id, X-User-Email, X-User-Scope gateway (removidos se um cliente os enviar) usuário autenticado, em quem os serviços confiam
X-Request-Id edge id de correlação, registrado em log por cada salto
X-Instance catalog qual réplica respondeu (lab 3)
X-Cache: HIT / MISS catalog resultado do cache (lab 5)

Portas já em uso?

Se algo na sua máquina já usa a porta 80, 5432 ou 6379 (um PostgreSQL local, por exemplo), pare-o, ou mude apenas o lado do host do mapeamento no docker-compose.yaml ("15432:5432"). Nunca mude a porta dentro do container: os outros serviços dependem dela.

1. Instale as ferramentas

A tabela lista para que serve cada ferramenta; as abas abaixo mostram como instalá-las em cada sistema. O k6 é um único binário1; o Docker Compose vem com o Docker Desktop ou como plugin do Docker Engine2.

Ferramenta Versão Usada em Por quê
Git qualquer recente todos os labs controle de versão, entrega de cada lab
Docker + Compose v2 Docker 27+ todos os labs todo serviço e banco roda em um container
JDK 21 (LTS) labs 1–11 serviços Spring Boot
Maven 3.9+ labs 1–11 build e dependências
uv recente labs 2, 12 instala o Python 3.12 e roda todo script e projeto Python (sem pip, sem venv)
Python 3.12 (via uv) labs 2, 12 scripts de resultados, o assistente de IA
k6 1.0+ labs 0–12 testes de carga (scripts em JavaScript)
kubectl + kind ou minikube recente labs 10–11 Kubernetes local
jq, curl qualquer todos os labs chamar e ler as APIs pelo terminal

Instale o Homebrew primeiro, depois:

brew install --cask docker          # Docker Desktop (or OrbStack: brew install --cask orbstack)
brew install --cask temurin@21      # Eclipse Temurin JDK 21
brew install maven uv k6 kubectl kind jq git
uv python install 3.12              # Python is managed by uv, not by Homebrew or pip

Abra o Docker Desktop uma vez para ele iniciar o engine, e dê a ele pelo menos 4 CPUs e 8 GB de memória (Settings → Resources).

# Docker Engine + Compose plugin (official convenience script) and run docker without sudo
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker "$USER" && newgrp docker

# JDK 21, Maven, tools
sudo apt-get update
sudo apt-get install -y openjdk-21-jdk maven git jq curl

# uv (Python package and project manager) and Python 3.12
curl -LsSf https://astral.sh/uv/install.sh | sh
uv python install 3.12

# k6 (official APT repository)
sudo gpg -k
sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg \
  --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" \
  | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update && sudo apt-get install -y k6

# kubectl and minikube
sudo snap install kubectl --classic
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube && rm minikube-linux-amd64

Instale o Docker Desktop para Windows, depois abra um terminal Bash e siga a aba Linux (pule as linhas do Docker Engine: o Docker Desktop já o fornece).

Sem o k6 instalado? Rode em um container

O k6 é um único binário, mas, se você não conseguir instalá-lo, a imagem oficial funciona com os mesmos scripts. A partir da raiz do repositório:

docker run --rm -i -v "$PWD":/w -w /w -e BASE_URL=http://host.docker.internal:8888 grafana/k6 run load/hello.js

Dentro de um container, localhost é o próprio container; host.docker.internal chega à sua máquina (no Linux, acrescente --add-host=host.docker.internal:host-gateway).

2. Verifique o seu ambiente

Salve o script abaixo como scripts/check-env.sh no seu repositório (próximo passo) e execute-o. Toda linha deve dizer ok.

scripts/check-env.sh
#!/usr/bin/env bash
# BoxOffice labs: checks that every tool is installed and prints its version.
# Usage: bash scripts/check-env.sh
set -u
missing=0

check() {            # check <label> <command line>
  local label="$1" cmd="$2" out
  if ! command -v "${cmd%% *}" >/dev/null 2>&1; then
    printf '  MISS  %-9s not found\n' "$label"; missing=$((missing + 1))
  elif out=$(eval "$cmd" 2>&1); then
    printf '  ok    %-9s %s\n' "$label" "$(echo "$out" | head -n 1)"
  else
    printf '  FAIL  %-9s %s\n' "$label" "$(echo "$out" | head -n 1)"; missing=$((missing + 1))
  fi
}

echo "Tools"
check git      "git --version"
check docker   "docker --version"
check compose  "docker compose version"
check java     "java -version"
check maven    "mvn -v"
check uv       "uv --version"
check k6       "k6 version"
check kubectl  "kubectl version --client"
check jq       "jq --version"
check curl     "curl --version"

echo "Kubernetes (lab 10): kind OR minikube is enough"
if command -v kind >/dev/null 2>&1 || command -v minikube >/dev/null 2>&1; then
  command -v kind >/dev/null 2>&1 && echo "  ok    kind      $(kind version 2>&1 | head -n 1)"
  command -v minikube >/dev/null 2>&1 && echo "  ok    minikube  $(minikube version --short 2>&1 | head -n 1)"
else
  echo "  MISS  kind / minikube"; missing=$((missing + 1))
fi

echo "Checks"
java_major=$(java -version 2>&1 | head -n 1 | sed -E 's/[^"]*"([0-9]+).*/\1/')
if [ "${java_major:-0}" -ge 21 ] 2>/dev/null; then
  echo "  ok    JDK $java_major (21 or newer)"
else
  echo "  MISS  JDK 21 or newer (found: ${java_major:-none})"; missing=$((missing + 1))
fi
# Python is installed and managed by uv (uv python install 3.12)
if py=$(uv python find '>=3.12' 2>/dev/null); then
  echo "  ok    Python $("$py" -c 'import platform; print(platform.python_version())') (via uv)"
else
  echo "  MISS  Python 3.12 or newer: run  uv python install 3.12"; missing=$((missing + 1))
fi
if docker info >/dev/null 2>&1; then
  echo "  ok    Docker daemon: $(docker info --format '{{.NCPU}} CPUs, {{.MemTotal}} bytes of memory')"
else
  echo "  MISS  Docker daemon is not running"; missing=$((missing + 1))
fi

echo
if [ "$missing" -eq 0 ]; then echo "All set."; else echo "$missing item(s) missing: fix them before lab 1."; fi
bash scripts/check-env.shTools
ok git git version 2.47.1
ok docker Docker version 28.4.0, build d8eb465
ok compose Docker Compose version v2.39.2
ok java openjdk version "21.0.8" 2025-07-15 LTS
ok maven Apache Maven 3.9.11
ok uv uv 0.9.2
ok k6 k6 v1.3.0 (go1.25.1, linux/amd64)
ok kubectl Client Version: v1.34.1
ok jq jq-1.7.1
ok curl curl 8.5.0 (x86_64-pc-linux-gnu)
Kubernetes (lab 10): kind OR minikube is enough
ok minikube v1.37.0
Checks
ok JDK 21 (21 or newer)
ok Python 3.12.12 (via uv)
ok Docker daemon: 8 CPUs, 16651931648 bytes of memory

All set.

As suas versões serão diferentes; o que importa é que nada diga MISS ou FAIL.

Falhas comuns

  • FAIL maven … JAVA_HOME environment variable is not defined correctly: aponte o JAVA_HOME para a pasta do JDK 21 (export JAVA_HOME=$(/usr/libexec/java_home -v 21) no macOS; /usr/lib/jvm/java-21-openjdk-amd64 no Ubuntu) e acrescente a linha ao seu ~/.zshrc ou ~/.bashrc.
  • MISS Docker daemon is not running: inicie o Docker Desktop (macOS/Windows) ou sudo systemctl start docker (Linux).
  • permission denied … docker.sock no Linux: você pulou o usermod -aG docker; saia da sessão e entre de novo.
  • MISS Python 3.12 or newer: rode uv python install 3.12. Nunca use pip install no Python do sistema: todo passo Python da disciplina passa pelo uv (uv run, uv add, uvx).

3. Crie o seu repositório

Todo o seu trabalho dos labs fica em um repositório, chamado boxoffice, criado por você no GitHub (privado; você adicionará os colegas de projeto depois). O repositório da disciplina tem o esqueleto de referência e é onde as atualizações do código dos labs são publicadas; o seu repositório é onde vivem o seu código e as suas medições.

mkdir boxoffice && cd boxoffice
git init -b main
mkdir -p services infra load results scripts

No fim do semestre ele terá esta cara — cada pasta aparece no lab indicado no comentário:

boxoffice/
📁 boxoffice/
├── YAML docker-compose.yaml        # lab 1, grows in every lab
├── Git .gitignore
├── Markdown README.md                  # how to run your BoxOffice
├── 📁 services/
│   ├── 📁 catalog/               # lab 1  (Spring Boot, port 8082)
│   ├── 📁 auth/                  # lab 4  (Spring Boot, port 8081)
│   ├── 📁 gateway/               # lab 4  (Spring Cloud Gateway, port 8080)
│   ├── 📁 inventory/             # lab 6  (Spring Boot, port 8083)
│   ├── 📁 order/                 # lab 7
│   ├── 📁 notification/          # lab 7
│   ├── 📁 payment/               # lab 9
│   └── 📁 assistant/             # lab 12 (FastAPI)
├── 📁 infra/
│   ├──  nginx/nginx.conf       # lab 3  (edge)
│   ├── 📁 postgres/              # lab 6  (replication)
│   └── 📁 pgbouncer/             # lab 6
├── 📁 load/                      # k6 scripts, from lab 0
│   └── JavaScript hello.js
├── 📁 results/                   # your measurements: lab0.md, lab1.md, ...
├── 📁 scripts/
│   └── GNU Bash check-env.sh
├── 📁 k8s/                       # lab 10
└── 📁 .github/workflows/         # lab 11

Acrescente um .gitignore na raiz:

.gitignore
# build output
target/
*.class
# IDEs and OS
.idea/
.vscode/
*.iml
.DS_Store
# local secrets: never commit them
.env
# k6 HTML reports are big; commit the JSON summaries and the tables in results/*.md
results/*.html

Depois crie o repositório no GitHub, faça o push e continue fazendo commits ao fim de cada lab:

git add . && git commit -m "lab 0: environment"
git remote add origin git@github.com:<your-user>/boxoffice.git
git push -u origin main

Um commit (ou tag) por lab

Crie uma tag ao fim de cada lab (git tag lab0 && git push --tags). Quando um lab posterior quebrar algo, git diff lab4 lab5 mostra exatamente o que mudou — a mesma disciplina que você usará nos deploys do lab 11.

4. Meça: a referência da sua máquina

Todo lab termina com uma medição, e esta define a referência: quanto o seu notebook consegue atender quando o servidor quase não faz nada? O alvo é um Nginx padrão devolvendo uma pequena página estática; qualquer número que você obtiver depois para o BoxOffice será menor, e a diferença é o custo do seu código, do seu banco e dos seus saltos de rede.

Salve o script como load/hello.js:

load/hello.js
// Lab 0: how fast is *your* machine? The target is a plain Nginx container.
//   docker run -d --rm --name hello -p 8888:80 nginx:1.30-alpine
//   k6 run -e VUS=10 load/hello.js
import http from 'k6/http';
import { check } from 'k6';

const BASE_URL = __ENV.BASE_URL || 'http://localhost:8888';

export const options = {
  vus: Number(__ENV.VUS || 10),          // closed model: N users, no think time
  duration: __ENV.DURATION || '20s',
  summaryTrendStats: ['avg', 'med', 'p(95)', 'p(99)', 'max'],
  thresholds: {
    http_req_failed: ['rate<0.01'],      // fewer than 1% errors
  },
};

export default function () {
  const res = http.get(`${BASE_URL}/`);
  check(res, { 'status is 200': (r) => r.status === 200 });
}

Suba o alvo, rode o k6 com 1, 10 e 50 usuários virtuais (VUs) e depois pare o alvo:

docker run -d --rm --name hello -p 8888:80 nginx:1.30-alpine
k6 run -e VUS=1  load/hello.js
k6 run -e VUS=10 load/hello.js
k6 run -e VUS=50 load/hello.js
docker stop hello
k6 run -e VUS=10 load/hello.js █ THRESHOLDS

http_req_failed
✓ 'rate<0.01' rate=0.00%

█ TOTAL RESULTS

checks_succeeded...: 100.00% 249184 out of 249184
HTTP
http_req_duration..............: avg=163.61µs med=119.66µs p(95)=405.54µs p(99)=824.01µs max=13.26ms
http_req_failed................: 0.00% 0 out of 249184
http_reqs......................: 249184 49808.803836/s
EXECUTION
vus............................: 10 min=10 max=10

Seus números dependem da máquina. Com o Docker Desktop (macOS, Windows) cada requisição também atravessa o encaminhamento de portas da VM, então espere algumas vezes menos do que no Linux nativo — cerca de 15.000 req/s com 10 VUs em um notebook Apple Silicon de 8 núcleos.

Leia o resumo assim:

  • http_reqs … /s é a vazão (throughput, em requisições por segundo, RPS).
  • http_req_duration dá a distribuição de latência: med é a mediana (p50), p(95)/p(99) são os percentis 95 e 99 — 1 requisição em 100 é mais lenta que o p99.
  • vus é a concorrência: cada usuário virtual envia uma requisição, espera a resposta e envia a próxima (um modelo de carga fechado).

Registre os resultados em results/lab0.md:

results/lab0.md
# Lab 0 — baseline

Machine: <CPU model>, <cores> cores, <RAM> GB; Docker resources: <CPUs> CPUs, <GB> GB

| VUs | Throughput (req/s) | p50 (ms) | p95 (ms) | p99 (ms) | Errors |
|----:|-------------------:|---------:|---------:|---------:|-------:|
|   1 |                    |          |          |          |        |
|  10 |                    |          |          |          |        |
|  50 |                    |          |          |          |        |

Little's Law check (VUs ≈ throughput × average latency):
- 10 VUs: ____ req/s × ____ s = ____
Pense antes: o que acontece entre 10 e 50 VUs?

Com 1 VU, a latência é puro tempo de serviço e a vazão é 1 / latência. Acrescentar VUs aumenta a vazão enquanto houver núcleos de CPU ociosos. Quando os núcleos estão ocupados, mais VUs só acrescentam espera: a vazão fica estável e a latência cresce na mesma proporção — a Lei de Little, L = λ × W, com L = VUs, λ = vazão e W = latência. Você verá esse joelho de novo, com serviços reais, no lab 2.

O k6 compete com o servidor

O k6 e o servidor dividem os mesmos núcleos de CPU, então, acima de algumas dezenas de milhares de requisições por segundo, você mede o k6 tanto quanto o Nginx. Para uma referência, tudo bem; no lab 2 o alvo será muito mais lento que o k6, e o problema desaparece.

5. Primeiro contato com o playground

O System Design Playground simula, sob carga e em segundos, os mesmos componentes que você vai construir. Cada lab incorpora o cenário que está prestes a medir de verdade, para você formar uma hipótese antes de rodar o k6.

Experimente: aperte Run no cenário monolith abaixo (um servidor de aplicação, um banco SQL). Aumente a carga até o p99 saltar. Qual componente satura primeiro? Anote a resposta — você vai confrontá-la com o seu próprio serviço catalog no lab 2.

Solução de problemas

Sintoma Causa Correção
Bind for 0.0.0.0:8888 failed: port is already allocated outro programa (ou um hello antigo) usa a porta 8888 docker rm -f hello, ou use outra porta: -p 8899:80 e k6 run -e BASE_URL=http://localhost:8899 load/hello.js
k6: command not found k6 não instalado ou fora do PATH instale (passo 1) ou use o comando com container da dica "Sem o k6 instalado?"
permission denied while trying to connect to the Docker daemon socket usuário Linux fora do grupo docker sudo usermod -aG docker "$USER", depois saia e entre de novo
Cannot connect to the Docker daemon Docker Desktop não iniciado inicie o Docker Desktop e espere "Engine running"
FAIL maven … JAVA_HOME JAVA_HOME aponta para nada ou para um JDK antigo aponte o JAVA_HOME para a pasta do JDK 21 (veja "Falhas comuns")
check-env.sh: line 1: #!/usr/bin/env: No such file o arquivo foi salvo com finais de linha do Windows (CRLF) sed -i 's/\r$//' scripts/check-env.sh (e configure o editor para LF)

Boas práticas neste lab

  • Confira o ferramental com um script, não de memória — scripts/check-env.sh mostra cada ferramenta e versão, então um ambiente quebrado aparece em segundos, não no meio de um teste de carga. Por que importa: toda medição da disciplina supõe o mesmo ambiente (Como estudar projeto de sistemas).
  • Mantenha segredos e saídas volumosas fora do Git — o .gitignore exclui .env e os relatórios HTML do k6, e mantém os resumos JSON e as tabelas em results/*.md. Segurança é um atributo de qualidade desde o primeiro dia (Requisitos).
  • Meça uma referência antes de mudar qualquer coisa — load/hello.js diz o que a sua máquina atende, a referência de todo número seguinte (Estimativas).
  • Anote cada medição com o seu ambiente — results/lab0.md registra máquina, taxa e latência; um número sem o ambiente não pode ser comparado (Tornando requisitos mensuráveis).

Limpeza

docker rm -f hello 2>/dev/null || true     # the baseline target, if still running
docker image prune -f                      # optional: remove dangling images

Mantenha tudo em boxoffice/: o lab 1 começa dele.

Entrega

  • bash scripts/check-env.sh imprime All set. (cole a saída em results/lab0.md).
  • O seu repositório boxoffice existe no GitHub com a estrutura de pastas, o .gitignore, o scripts/check-env.sh e o load/hello.js, com a tag lab0.
  • results/lab0.md tem a tabela de referência preenchida (1, 10 e 50 VUs) e a verificação da Lei de Little.
  • Você rodou o cenário monolith no playground e anotou qual componente satura primeiro.
  • Quiz respondido.

Estado final

Ao fim deste lab o seu repositório contém (o overlay code/ do lab mais os seus resultados):

boxoffice/ after lab 0
📁 boxoffice/
├── Git .gitignore
├── 📁 load/
│   └── JavaScript hello.js
├── 📁 results/
│   └── Markdown lab0.md
└── 📁 scripts/
    └── GNU Bash check-env.sh

Próximo: Lab 1 — Primeiro serviço.


  1. Documentação do Grafana k6, Running k6 e Install k6. ↩

  2. Documentação do Docker, Docker Compose. ↩