Skip to content

About

Download com failover transparente entre réplicas usando HTTP Range Requests

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tema 08 — Transparência nas Falhas

Disciplina: Sistemas Distribuídos Curso: Bacharelado em Sistemas de Informação — IFBA Professor: Leonardo Barreto Campos


O que o sistema faz

Um cliente solicita o download de um arquivo. O sistema busca esse arquivo em uma réplica (servidor de arquivos). Se a conexão com essa réplica cair durante o download, o sistema detecta a falha automaticamente e continua o download de onde parou, usando outra réplica — sem que o cliente precise fazer nada. Isso é a transparência nas falhas.


Arquitetura

┌──────────────────────────────────────────────────────────────┐
│  MÁQUINA 1 — Coordinator (:8080)                             │
│                                                              │
│  /admin  → painel do operador (monitora réplicas e downloads)│
│  /user   → painel do cliente (lista arquivos e faz download) │
│                                                              │
│  Lógica: health check, proxy do download, failover           │
└───────────────────┬──────────────────────────────────────────┘
                    │ HTTP Range Requests
          ┌─────────┴──────────┐
          ▼                    ▼
┌──────────────────┐  ┌──────────────────┐
│  MÁQUINA 2       │  │  MÁQUINA 3       │
│  Réplica A :9001 │  │  Réplica B :9001 │
│  (tem os arquivos│  │  (mesmos arquivos│
│   em shared/files│  │   em shared/files│
└──────────────────┘  └──────────────────┘

MÁQUINAS 4 e 5 → apenas abrem o browser
                  não precisam de Go instalado
                  não precisam dos arquivos

Rotas da API

O sistema expõe as seguintes rotas da API para comunicação interna e interfaces web:

Coordinator (Máquina 1)

Rota Método Descrição
/user GET Interface do cliente (HTML)
/admin GET Interface do operador (HTML)
/api/files GET Lista os arquivos disponíveis (proxy para uma réplica)
/api/replicas GET Status atual de todas as réplicas
/api/download/{arquivo} GET Download com failover automático
/events GET Stream SSE de eventos em tempo real

Réplica (Máquinas 2 e 3)

Rota Método Descrição
/health GET Retorna {"status":"ok"} — usado pelo health check
/files GET Lista os arquivos em shared/files/
/download/{arquivo} GET/HEAD Serve o arquivo, com suporte a Range Requests

Qual IP usar para acessar?

Sempre o IP da Máquina 1 (Coordinator).

O coordinator é o único que serve o frontend. As réplicas não têm interface web — elas só servem os bytes dos arquivos para o coordinator.

Quem acessa URL
Operador (Máq 1) http://localhost:8080/admin
Clientes (Máq 4 e 5) http://<IP_DA_MÁQUINA_1>:8080/user

Como descobrir o IP da Máquina 1:

# No Windows:
ipconfig

# No Linux/Mac:
ip a
# ou
hostname -I

Procure o IP na linha IPv4 (Windows) ou inet (Linux) da interface de rede da máquina (geralmente começa com 192.168.x.x ou 10.x.x.x). O coordinator também imprime o endereço no terminal quando inicia.


Estrutura do projeto

failover-trasnparency/
├── main.go              ← Coordinator: proxy, failover, health check, SSE
├── go.mod
├── replica/
│   └── main.go          ← Servidor de réplica: serve arquivos com Range Request
├── static/
│   ├── admin.html        ← Frontend do operador (/admin)
│   └── user.html         ← Frontend do cliente (/user)
└── shared/
    └── files/            ← Coloque aqui os arquivos nas máquinas RÉPLICA

Onde os arquivos precisam estar:

Máquina Precisa dos arquivos em shared/files/?
Máquina 1 (Coordinator) NÃO — só faz proxy
Máquina 2 (Réplica A) SIM
Máquina 3 (Réplica B) SIM (cópia idêntica)
Máquinas 4 e 5 (Clientes) NÃO — só usam o browser

Pré-requisitos

  • Go 1.22+ instalado nas máquinas 1, 2 e 3
  • Todas as máquinas na mesma rede (mesmo Wi-Fi ou cabo do laboratório)
  • Browser nas máquinas 4 e 5 (qualquer um)

Passo a passo — executar em 5 máquinas

Passo 1 — Clonar/copiar o projeto (Máquinas 1, 2 e 3)

Copie a pasta do projeto para cada uma das três máquinas. A forma mais fácil em laboratório é via pendrive ou git clone.

Passo 2 — Colocar os arquivos nas réplicas (Máquinas 2 e 3)

Nas Máquinas 2 e 3, coloque os arquivos que serão disponibilizados para download dentro de shared/files/. Ambas precisam ter os mesmos arquivos para o failover funcionar.

# Exemplo: gerar um arquivo de teste de 50MB (Linux/Mac)
dd if=/dev/urandom of=shared/files/teste-50mb.bin bs=1M count=50

# Windows (PowerShell)
$bytes = New-Object byte[] 52428800
[System.IO.File]::WriteAllBytes("shared\files\teste-50mb.bin", $bytes)

Dica: use um arquivo grande o suficiente para ter tempo de simular a falha durante o download. 20–100 MB é ideal.

Passo 3 — Iniciar as Réplicas (Máquinas 2 e 3)

Na Máquina 2, abra o terminal na pasta do projeto e execute:

go run ./replica/ -port 9001 -name "Replica-A" -delay 150ms

Na Máquina 3, execute:

go run ./replica/ -port 9001 -name "Replica-B" -delay 150ms

O terminal vai mostrar o IP e a porta de cada réplica, por exemplo:

╔══════════════════════════════════════════╗
║  REPLICA SERVER: Replica-A               ║
║  Address: 192.168.1.11:9001              ║
║  Files:   ./shared/files                 ║
║  Delay:   150ms                          ║
╚══════════════════════════════════════════╝

O flag -delay adiciona um atraso proposital a cada bloco de 32KB enviado. Isso torna o download mais lento e dá tempo de desligar a réplica durante a demo.

Passo 4 — Iniciar o Coordinator (Máquina 1)

Abra o terminal na pasta do projeto e execute, substituindo pelos IPs reais das Máquinas 2 e 3:

go run . -replicas "192.168.1.11:9001,192.168.1.12:9001"

O terminal vai mostrar:

╔══════════════════════════════════════════════╗
║  COORDINATOR SERVER                          ║
║  Address:  192.168.1.10:8080                 ║
║  Admin:    http://192.168.1.10:8080/admin    ║
║  User:     http://192.168.1.10:8080/user     ║
║  Replicas: 2 configured                      ║
╚══════════════════════════════════════════════╝
  → Replica: 192.168.1.11:9001
  → Replica: 192.168.1.12:9001

Passo 5 — Abrir as interfaces

Na Máquina 1 (operador):

http://localhost:8080/admin

Nas Máquinas 4 e 5 (clientes) — apenas abrir o browser:

http://192.168.1.10:8080/user

(use o IP real que apareceu no terminal do coordinator)


Como fazer a demonstração do failover

  1. Abra /admin no operador e /user nos clientes
  2. Confirme que as réplicas aparecem como ONLINE (verde) no admin
  3. Um cliente clica em Download em um arquivo grande
  4. Observe a barra de progresso avançando no /user e o monitor no /admin
  5. Encerre a Réplica A com Ctrl+C no terminal da Máquina 2 (ou puxe o cabo)
  6. Observe nos logs:
    • CONEXÃO PERDIDA com 192.168.1.11:9001
    • FAILOVER: Reconectando à 192.168.1.12:9001 byte XXXXX
  7. A barra de progresso fica laranja e o símbolo ⚡ aparece
  8. O download continua e conclui normalmente
  9. No /admin a Réplica A aparece como OFFLINE (vermelho piscando)

E se o Coordinator (Máquina 1) cair?

O coordinator é o ponto central da arquitetura — ele é o único que serve o frontend e coordena os downloads. Se ele cair:

  • O /user e o /admin ficam inacessíveis (não tem como acessar pelo browser)
  • Qualquer download em andamento é interrompido
  • As réplicas continuam rodando normalmente, mas ninguém consegue usá-las

Isso é esperado. O tema 08 demonstra transparência nas falhas de réplicas de arquivo. A falha do coordinator é um problema diferente (coordenador tolerante a falhas requer eleição de líder, Raft, Paxos — muito além do escopo). Na prática do seminário, o coordinator fica na máquina do professor ou em uma máquina estável. O que pode e deve cair durante a demo são as réplicas.


O que roda em cada "máquina"?

"Máquina" = qualquer coisa com browser ou terminal. Pode ser um PC real, um terminal diferente no mesmo PC, um celular, um tablet. O sistema não sabe a diferença.

Papel O que precisa O que roda
Máquina 1 — Coordinator PC com Go instalado go run . no terminal + browser no /admin
Máquina 2 — Réplica A PC/terminal com Go + os arquivos go run ./replica/ -port 9001
Máquina 3 — Réplica B PC/terminal com Go + os arquivos go run ./replica/ -port 9002
Clientes (4, 5...) Só um browser Abrir http://<ip-coordinator>:8080/user

Sim, tudo pode rodar em terminais do mesmo PC. Isso é o "teste local" da seção abaixo.

Sim, o celular funciona como cliente — basta estar no mesmo WiFi e abrir o /user no browser do celular.


Teste com seu laptop + celular/namorada no mesmo WiFi

Todo o servidor roda no seu laptop. O celular ou outro dispositivo só abre o browser.

Passo 1 — Descobrir o IP do seu laptop (Windows)

Abra o Prompt de Comando (Win + R → cmd → Enter) e execute:

ipconfig | findstr "IPv4"

A saída vai ser algo assim:

   Endereço IPv4. . . . . . . . .  . . . . : 192.168.1.105

Esse IP é o endereço do seu laptop na rede WiFi. É o que o celular/namorada vai usar no browser.

O coordinator também imprime esse IP automaticamente quando inicia — você pode copiar direto de lá.

Passo 2 — Liberar a porta 8080 no Firewall do Windows

O Windows bloqueia conexões externas por padrão. Abra o PowerShell como Administrador e execute:

netsh advfirewall firewall add rule name="SD-Coordinator" dir=in action=allow protocol=TCP localport=8080

Só precisa fazer uma vez. Para desfazer depois:

netsh advfirewall firewall delete rule name="SD-Coordinator"

Passo 3 — Criar um arquivo de teste grande

No PowerShell (na pasta do projeto), gere um arquivo grande o suficiente para ter tempo de simular a falha:

# Cria um arquivo de 30MB
$bytes = New-Object byte[] (30 * 1024 * 1024)
(New-Object Random).NextBytes($bytes)
[System.IO.File]::WriteAllBytes("$PWD\shared\files\teste-30mb.bin", $bytes)

Passo 4 — Abrir 3 terminais no seu laptop

Na pasta do projeto, abra 3 terminais separados (pode usar o terminal do VSCode com + ou janelas separadas):

Terminal 1 — Réplica A:

go run ./replica/ -port 9001 -name "Replica-A" -delay 200ms

Terminal 2 — Réplica B:

go run ./replica/ -port 9002 -name "Replica-B" -delay 200ms

Terminal 3 — Coordinator (inicie por último):

go run . -replicas "127.0.0.1:9001,127.0.0.1:9002"

O Terminal 3 vai imprimir o IP da sua máquina:

║  Admin:    http://192.168.1.105:8080/admin    ║
║  User:     http://192.168.1.105:8080/user     ║

Passo 5 — Cada dispositivo acessa sua URL

Dispositivo URL
Seu laptop (admin) http://localhost:8080/admin
Celular / namorada http://192.168.1.105:8080/user ← o IP do Terminal 3

No celular: abrir o browser (Chrome, Safari) e digitar a URL. Precisa estar no mesmo WiFi.

Passo 6 — Demonstrar o failover

  1. No celular/namorada: clicar em Download
  2. No seu laptop: observar o progresso no /admin
  3. Enquanto o download avança: Ctrl+C no Terminal 1 (mata a Réplica A)
  4. O sistema detecta a falha e automaticamente troca para a Réplica B
  5. A barra fica laranja com ⚡ — o download continua e termina normalmente

Teste local (sem múltiplas máquinas)

Para testar tudo em um só computador, abra 3 terminais:

# Terminal 1 — Réplica A
go run ./replica/ -port 9001 -name "Replica-A" -delay 200ms

# Terminal 2 — Réplica B
go run ./replica/ -port 9002 -name "Replica-B" -delay 200ms

# Terminal 3 — Coordinator
go run . -replicas "127.0.0.1:9001,127.0.0.1:9002"

Acesse:

  • Admin: http://localhost:8080/admin
  • Cliente: http://localhost:8080/user

Para simular a falha: feche o Terminal 1 (Ctrl+C) durante um download.


Flags disponíveis

Coordinator (main.go)

Flag Padrão Descrição
-port 8080 Porta do servidor
-static ./static Pasta com os HTMLs
-replicas — Obrigatório. IPs das réplicas separados por vírgula
-health-interval 2s Intervalo do health check

Réplica (replica/main.go)

Flag Padrão Descrição
-port 9001 Porta do servidor
-name replica-{port} Nome exibido nos logs
-dir ./shared/files Pasta com os arquivos
-delay 100ms Atraso por chunk de 32KB (para demo)

Como funciona o failover (detalhes técnicos)

  1. Cliente abre /user e clica em Download
  2. Coordinator recebe a requisição em /api/download/{arquivo}
  3. Coordinator faz HEAD na Réplica A para obter o tamanho total do arquivo
  4. Coordinator faz GET com Range: bytes=0-{total} na Réplica A
  5. Coordinator transmite os bytes recebidos direto para o browser do cliente
  6. A cada chunk, o coordinator envia o progresso via SSE para todos os browsers conectados
  7. Se a Réplica A cai (timeout ou erro de rede):
    • O coordinator registra quantos bytes já foram enviados
    • Busca outra réplica saudável na lista
    • Faz GET com Range: bytes={bytesRecebidos}-{total} na Réplica B
    • Continua o streaming exatamente de onde parou
  8. O arquivo chega completo ao browser — a troca de réplica é transparente para o usuário

Stack

  • Backend: Go 1.22+ (stdlib pura, zero dependências)
  • Frontend: HTML + CSS + JavaScript vanilla
  • Protocolo de failover: HTTP Range Requests (Range: bytes=X-Y)
  • Tempo real: Server-Sent Events (SSE)

About

Download com failover transparente entre réplicas usando HTTP Range Requests

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages