Padronizado pela OMG (Object Management Group) para unificar comunicação entre objetos em linguagens diferentes.
Disciplina: DEE354 – Sistemas Distribuídos
Universidade Federal do Paraná
Professor: Prof. Jéfer – jefer@ufpr.br
Carga Horária: 60 horas (15 semanas, 4h/semana)
Faltas: 60 horas x 0,25 = 15 horas ou 7 aulas
Pré-requisitos: Redes de Computadores, Sistemas Operacionais, Programação Concorrente
LTSP (Linux Terminal Server Project) é um projeto open source que permite a execução de múltiplas sessões de usuários, com processamento centralizado em um único servidor Linux.
Em vez de computadores completos, os usuários utilizam Thin Clients — máquinas simples, com pouco poder de processamento, que apenas exibem a interface gráfica e enviam comandos de entrada (mouse/teclado).
SSH
, X11
ou VNC
.ltsp-manager
e imagens baseadas em systemd-nspawn
.Definição: Sistema composto por múltiplos computadores (nós) interligados, operando como uma única entidade lógica para:
x86_64, ARM, GPUs (NVIDIA A100), TPUs, FPGAs
Infiniband (200Gbps), Ethernet, NVLink (GPU-to-GPU)
Linux (CentOS/Rocky), SLURM, Kubernetes, MPI, OpenMP
4.000 nós Linux (Top500) para renderização 3D.
70 PS2 simulando buracos negros (Universidade de Illinois).
16.000 GPUs NVIDIA para treino de IA.
AWS Batch, Azure CycleCloud, Google HPC Toolkit.
Clusters descentralizados (ex.: carros autônomos).
Sistema distribuído que integra recursos computacionais heterogêneos (CPU, GPU, armazenamento) de diferentes domínios administrativos para resolver problemas em larga escala.
Geograficamente disperso
Multi-organizacional
Computação voluntária
Característica | Cluster | Grid |
---|---|---|
Localização | Único data center | Global (várias instituições) |
Gestão | Uma entidade | Múltiplos domínios |
Hardware | Homogêneo | Heterogêneo (CPU/GPU/ARM) |
Comunicação | Rede local (Infiniband) | Internet (alta latência) |
Casos de Uso | HPC, Big Data | Ciência cidadã, projetos globais |
Analisou sinais de rádio astronômicos com 5 milhões de voluntários.
Simulação de dobra de proteínas para pesquisa de doenças (ex: COVID-19).
Processou dados do Large Hadron Collider (CERN) em 170 data centers.
Integração com dispositivos IoT (ex: carros autônomos compartilhando poder computacional).
Incentivos via tokens para participantes (ex: Golem Network).
Extensão da computação em nuvem que aproxima processamento e armazenamento dos dispositivos de borda, criando uma camada intermediária ("névoa") entre IoT e cloud.
Latência < 10ms
Processamento local
Segurança distribuída
Exemplo: Em uma fábrica inteligente, sensores (edge) enviam dados para um gateway (fog) que filtra informações antes de enviar à nuvem.
Semaforos inteligentes processam dados de tráfego localmente para evitar congestionamentos.
Gateways em fábricas detectam falhas em máquinas em tempo real (manutenção preditiva).
Carros compartilham dados de tráfego via RSUs (Roadside Units) em tempo real.
Cenário | Cloud | Fog |
---|---|---|
Latência | 100-500ms | < 10ms |
Largura de Banda | Alto consumo | Otimizada (filtro local) |
Custo | Pay-as-you-go | Investimento inicial |
Exemplo | Big Data analytics | Monitoramento de saúde em tempo real |
Autenticação distribuída em dispositivos heterogêneos (ex: padrão IEEE 1934-2018: Standard for Adoption of OpenFog Reference Architecture for Fog Computing.).
Modelos de ML compactos (TinyML) rodando em gateways.
Network slicing para priorizar tráfego crítico.
Sistemas distribuídos exigem tecnologias adaptadas a três pilares:
MPI: 0.5µs (Infiniband) vs. gRPC: 100µs
Erlang: 2M conexões/nó vs. Java: 50K
OTP (Erlang) vs. Kubernetes (Go)
2B usuários com OTP para gerência de falhas.
1B requisições/dia entre microsserviços.
Vantagem: Segurança de memória sem GC. Ex: Kafka.
Vantagem: Escalabilidade automática. Ex: AWS Lambda.
Vantagem: Processamento local. Ex: TinyML.
Padronizado pela OMG (Object Management Group) para unificar comunicação entre objetos em linguagens diferentes.
"Permitia que um objeto Java chamasse métodos de um objeto C++ remotamente, como se fosse local."
// Calculator.idl module Calculadora { interface Operacoes { double soma(in double a, in double b); double subtrai(in double a, in double b); }; };
// Servidor Java public class OperacoesImpl extends OperacoesPOA { public double soma(double a, double b) { return a + b; } // ... outras implementações }
O IDL é compilado para stubs (cliente) e skeletons (servidor).
Integração entre mainframes (COBOL) e frontends Java.
Comunicação em sistemas de defesa (ex: controle de tráfego aéreo).
CORBA | gRPC | |
---|---|---|
Protocolo | IIOP (binário) | HTTP/2 + Protobuf |
Performance | ~500µs latency | ~100µs latency |
Complexidade | Alta (IDL, ORB) | Moderada |
✔ Pioneiro em objetos distribuídos
✔ Padrão multi-linguagem
✖ Middleware não deve ser invisível
✖ Simplicidade > Features
Criado por um consórcio de universidades e laboratórios para padronizar a comunicação em clusters HPC.
"Linguagem neutra: funciona com C, C++, Fortran, Python (via mpi4py)."
MPI_Send(buffer, count, datatype, dest, tag, comm); MPI_Recv(buffer, count, datatype, source, tag, comm, status);
MPI_Bcast(data, count, datatype, root, comm); MPI_Reduce(sendbuf, recvbuf, count, datatype, op, root, comm);
MPI_COMM_WORLD
agrupa todos os processos.#include <mpi.h> #include <stdio.h> int main(int argc, char** argv) { MPI_Init(&argc, &argv); int rank, size; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); printf("Hello from rank %d of %d\n", rank, size); MPI_Finalize(); return 0; }
from mpi4py import MPI comm = MPI.COMM_WORLD rank = comm.Get_rank() size = comm.Get_size() print(f"Hello from rank {rank} of {size}")
Compilação (C): mpicc hello.c -o hello && mpirun -np 4 ./hello
Fugaku (Japão): 7.3M núcleos usando MPI+OpenMP.
CESM (EUA): Simulações com 100+ variáveis em paralelo.
MPI | OpenMP | gRPC | |
---|---|---|---|
Escala | Clusters (1K+ nós) | Multicore (1 nó) | Microsserviços |
Latência | 0.5µs (Infiniband) | 10ns (memória) | 100µs (rede) |
Melhor Caso | Cálculos científicos | Paralelismo fino | Comunicação heterogênea |
MPI_Send
direto entre GPUs."Framework para paralelismo em memória compartilhada com diretivas simples em C/C++/Fortran."
Latência: ~10ns (acesso direto à memória RAM)
Threads: Gerenciadas automaticamente (1 por núcleo)
Modelo: Fork-Join (threads criadas/destruídas sob demanda)
private
(cópia por thread) ou shared
(acesso concorrente).#pragma omp parallel
, for
, reduction
.π ≈ 4 × (pontos dentro do círculo / pontos totais). Paralelize a geração de pontos:
#include <stdio.h> #include <stdlib.h> int main() { int points = 1e6; int inside = 0; for (int i = 0; i < points; i++) { double x = (double)rand() / RAND_MAX; double y = (double)rand() / RAND_MAX; if (x*x + y*y <= 1) inside++; } double pi = 4.0 * inside / points; printf("π ≈ %f\n", pi); return 0; }
#include <omp.h> // ... #pragma omp parallel for reduction(+:inside) for (int i = 0; i < points; i++) { // Geração de pontos (igual ao serial) } printf("π ≈ %f (%d threads)\n", pi, omp_get_max_threads());
Compilação: gcc -fopenmp pi.c -o pi && OMP_NUM_THREADS=4 ./pi
Paralelize a soma de um vetor grande usando reduction
:
double sum = 0; for (int i = 0; i < N; i++) { sum += array[i]; }
double sum = 0; #pragma omp parallel for reduction(+:sum) for (int i = 0; i < N; i++) { sum += array[i]; }
Compilação: gcc -fopenmp sum.c -o sum
#pragma omp parallel for schedule(static, chunk)
para controlar o balanceamento de carga.race conditions
em variáveis compartilhadas sem reduction
ou critical
Paralelize este código com OpenMP:
double result[N]; for (int i = 0; i < N; i++) { result[i] = 0; for (int j = 0; j < N; j++) { result[i] += matrix[i][j] * vector[j]; } }
#pragma omp parallel for for (int i = 0; i < N; i++) { result[i] = 0; #pragma omp simd // Otimização adicional for (int j = 0; j < N; j++) { result[i] += matrix[i][j] * vector[j]; } }
Dica: Note o uso de simd
para vetorização interna do loop.
"Framework moderno para chamadas remotas (RPC) usando HTTP/2 e Protocol Buffers, desenvolvido pelo Google."
Latência: ~100µs (5x mais rápido que REST)
Streaming: Suporte a fluxos bidirecionais
Segurança: TLS nativo e autenticação
syntax = "proto3"; service Calculator { rpc Add (AddRequest) returns (AddResponse); } message AddRequest { int32 a = 1; int32 b = 2; } message AddResponse { int32 result = 1; }
Compilação: protoc --go_out=. --python_out=. calculator.proto
package main import ( "context" "log" "net" "google.golang.org/grpc" pb "caminho/do/proto" ) type server struct{} func (s *server) Add(ctx context.Context, req *pb.AddRequest) (*pb.AddResponse, error) { return &pb.AddResponse{Result: req.A + req.B}, nil } func main() { lis, _ := net.Listen("tcp", ":50051") s := grpc.NewServer() pb.RegisterCalculatorServer(s, &server{}) s.Serve(lis) }
import grpc import calculator_pb2 import calculator_pb2_grpc channel = grpc.insecure_channel('localhost:50051') stub = calculator_pb2_grpc.CalculatorStub(channel) response = stub.Add(calculator_pb2.AddRequest(a=5, b=3)) print("Resultado:", response.result) # Output: 8
gRPC | REST/JSON | |
---|---|---|
Protocolo | HTTP/2 (binário) | HTTP/1.1 (texto) |
Payload | Protocol Buffers (compacto) | JSON (verboso) |
Streaming | ✅ Bidirecional | ❌ Unidirecional |
Casos de Uso | Microsserviços, IoT | APIs públicas |
Comunicação entre microsserviços (1B+ requisições/dia).
Originalmente criado para conectar serviços na nuvem.
Modifique o exemplo para suportar streaming bidirecional:
service Chat { rpc SendMessage (stream Message) returns (stream MessageResponse); }
Use yield
no Python e stream.Send()
no Go para enviar mensagens assíncronas.
"Protocolo que permite acesso transparente a arquivos remotos como se fossem locais, usando RPC para comunicação."
Origem: Sun Microsystems (1984)
Protocolo: Baseado em RPC (chamadas remotas)
Versões: NFSv3 (RFC 1813), NFSv4 (RFC 3530)
open
, read
, etc.).# Instale o NFS no servidor (Ubuntu) sudo apt install nfs-kernel-server # Configure o diretório exportado sudo mkdir /shared sudo chown nobody:nogroup /shared echo "/shared *(rw,sync,no_subtree_check)" | sudo tee /etc/exports # Inicie o serviço sudo exportfs -a sudo systemctl start nfs-kernel-server
# Instale o cliente NFS sudo apt install nfs-common # Monte o diretório remoto sudo mkdir -p /mnt/nfs/shared sudo mount -t nfs servidor:/shared /mnt/nfs/shared # Verifique df -h | grep nfs ls /mnt/nfs/shared # Arquivos aparecem como locais!
NFSv3 (1995) | NFSv4 (2000) | |
---|---|---|
Estado | Stateless | Stateful |
Segurança | Limitada (Unix auth) | Kerberos, ACLs |
Performance | UDP (rápido, não confiável) | TCP (confiável) |
Firewall | Múltiplas portas RPC | Porta única (2049) |
Compartilhamento de datasets grandes entre nós de computação.
Armazenamento centralizado para máquinas virtuais.
rw
(leitura/escrita) para um cliente.Adicione a montagem automática no /etc/fstab
do cliente:
servidor:/shared /mnt/nfs/shared nfs defaults 0 0
Definição: Capacidade de integrar diferentes tecnologias em um mesmo sistema:
Conceito: Tecnologia integrada ao ambiente do usuário, invisível e disponível em qualquer lugar:
Agricultura de Precisão: Sensores monitoram umidade do solo e otimizam irrigação (economia de 30% de água).
Cidades Inteligentes: Sensores em lixeiras acionam coleta quando cheias (ex: Barcelona).
Energia: Baterias durando anos (ex: LoRaWAN = 10km com AA).
Conectividade: Baixa largura de banda (ex: Zigbee = 250kbps).
Roteamento: Protocolos como RPL para redes mesh.
#include <SPI.h> #include <LoRa.h> // Pinos (ajuste para seu hardware) #define SCK 5 // GPIO5 #define MISO 19 // GPIO19 #define MOSI 27 // GPIO27 #define SS 18 // GPIO18 #define RST 14 // GPIO14 #define DIO0 26 // GPIO26 void setup() { Serial.begin(115200); LoRa.setPins(SS, RST, DIO0); if (!LoRa.begin(915E6)) { // Frequência para Brasil Serial.println("Falha ao iniciar LoRa!"); while (1); } Serial.println("LoRa inicializado!"); }
void loop() { float temperatura = readTemperature(); // Simulação float umidade = readHumidity(); // Envia pacote LoRa LoRa.beginPacket(); LoRa.print("T:"); LoRa.print(temperatura); LoRa.print("|H:"); LoRa.print(umidade); LoRa.endPacket(); delay(10000); // Envia a cada 10s }
void onReceive(int packetSize) { if (packetSize == 0) return; String data; while (LoRa.available()) { data += (char)LoRa.read(); } Serial.print("Dados recebidos: "); Serial.println(data); // Processa dados (ex: aciona alarme se temperatura > 30°C) } void loop() { LoRa.onReceive(onReceive); LoRa.receive(); }
Biblioteca: LoRa.h
| Plataforma: Arduino IDE/PlatformIO
Starlink (SpaceX): 4,000+ satélites LEO para Internet global (velocidade ~300Mbps).
GPS (EUA): 24 satélites MEO para posicionamento (precisão ~3m).
Latência: GEO: 500ms ida e volta (vs fibra óptica: ~10ms).
Protocolos: DTN (Delay-Tolerant Networking) para conexões instáveis.
Ambiente Hostil: Radiação cósmica, lixo espacial.
Critério | Redes de Sensores (WSN) | Redes de Satélites |
---|---|---|
Custo | 💰 Baixo (nó sensor: $10-$100) | 🚀 Alto (satélite: $500k-$500M) |
Cobertura | 📶 Local (até 10km com LoRa) | 🌍 Global (incluindo oceanos) |
Latência | ⚡ Baixa (<100ms) | ⏳ Alta (LEO: 20ms, GEO: 500ms) |
Manutenção | 🔧 Troca de baterias | 🛰️ Impossível (em órbita) |
Melhor Caso | 🏭 IoT industrial, agricultura | 🌐 Internet remota, GPS |
Sensores no solo: Medem desmatamento (via vibração e som).
Satélites CubeSat: Validam dados e retransmitem.
Nuvem: Aciona alertas em tempo real.
Cenário: Monitorar vulcões ativos em áreas remotas.
Resposta: Combinação de ambas! Sensores no solo (WSN) para dados precisos + CubeSats para retransmissão em áreas sem infraestrutura.
Por quê? WSN é mais barato para alta densidade de sensores, enquanto satélites garantem cobertura em locais inacessíveis.
Use o simulador TOSSIM (para TinyOS) ou Cooja (para ContikiOS):
# Exemplo no Cooja (simulando sensores em uma floresta) 1. Crie 10 nós sensores virtuais 2. Implemente roteamento mesh com RPL 3. Monitore consumo de energia
Critério | Cliente-Servidor | P2P | Microsserviços |
---|---|---|---|
Acoplamento | Alto | Baixo | Médio |
Escalabilidade | Vertical | Horizontal | Horizontal |
Ponto Único de Falha | Sim | Não | Parcial |
Complexidade | Baixa | Alta | Média-Alta |
Responda as seguintes questões:
Responda as seguintes questões:
O LTSP transforma um único servidor em host para vários terminais leves. É útil em ambientes que buscam economia de hardware, administração centralizada e baixo consumo de recursos, como laboratórios de escolas ou empresas.
Um cluster normalmente fica concentrado em um único local, com nós homogêneos geridos por uma única entidade. Já um grid pode abranger diversos domínios administrativos e físicos, combinando recursos heterogêneos de várias instituições.
Quando o sistema requer baixa latência (tempo de resposta muito curto) ou quando é desejável pré-processar dados perto da fonte para reduzir o tráfego na nuvem. Exemplos: aplicações de IoT industrial, carros autônomos e cidades inteligentes.
Porque em um cluster MPI cada nó possui seu próprio SO e se comunica via rede para coordenar a computação, caracterizando a independência e interconexão de componentes típica de sistemas distribuídos, mesmo com foco em alto desempenho.
Sistemas distribuídos possibilitam o processamento paralelo, maior escalabilidade, tolerância a falhas e melhor aproveitamento de recursos, fundamentais para aplicações de alta performance e computação em nuvem.
Na comunicação síncrona, o remetente espera a resposta antes de prosseguir (RPC). Na assíncrona, a mensagem é enviada e o remetente pode continuar, recebendo a resposta em outro momento (filas de mensagens, publish-subscribe).
Os principais componentes são: ORB (Object Request Broker) que gerencia a comunicação, IDL (Interface Definition Language) para definir interfaces, Stubs/Skeletons como proxies locais, e o Interface Repository que armazena definições. O ORB atua como intermediário, permitindo que objetos distribuídos se comuniquem transparentemente.
Enquanto operações ponto-a-ponto (como MPI_Send/MPI_Recv) conectam dois processos específicos, as operações coletivas (MPI_Bcast, MPI_Reduce, MPI_Gather) envolvem grupos de processos. Estas otimizam padrões comuns como broadcast, redução e sincronização, sendo implementadas de forma eficiente pelo runtime do MPI.
OpenMP é para memória compartilhada (multicore), usando diretivas de compilação e threads, enquanto MPI é para memória distribuída (clusters), usando troca explícita de mensagens. OpenMP tem menor overhead mas escala menos, MPI é mais complexo mas escala para milhares de nós.
Abordagens distribuídas permitem: processamento local para reduzir transmissão (edge computing), auto-organização da rede, tolerância a falhas (já que sensores podem falhar), e algoritmos como data aggregation que combinam dados de múltiplos sensores antes do envio para economizar energia.
1) Request-Reply (RPC/REST): para interações síncronas que exigem resposta imediata. 2) Publish-Subscribe: quando múltiplos consumidores precisam receber eventos assincronamente. 3) Mensageria ponto-a-ponto (filas): para processamento assíncrono com garantia de entrega e balanceamento de carga entre workers.
Porque: 1) Reduz latência para decisões em tempo real (ex: parada de emergência), 2) Funciona mesmo com conectividade intermitente com a nuvem, 3) Processa localmente grandes volumes de dados de sensores antes do envio, e 4) Atende requisitos de privacidade/segurança mantendo dados sensíveis no local.
CORBA promove acoplamento forte com interfaces binárias complexas via ORB, enquanto microsserviços usam APIs leves (REST/gRPC) e independência de implementação. Microsserviços favorecem decentralização, tolerância a falhas e deploy independente, enquanto CORBA busca transparência total de localização.
MPI oferece: 1) Tipos de dados derivados para lidar com diferentes representações, 2) Operações coletivas que se adaptam à topologia, 3) Comunicações não-bloqueantes para sobrepor computação e comunicação, e 4) Processos dinâmicos (MPI_Comm_spawn) para integrar nós heterogêneos durante a execução.
Usam algoritmos como: 1) Bully Algorithm (nós "desafiam" com IDs), 2) Ring-based (mensagens circulam), adaptados para restrições de energia. Frequentemente elegem líderes temporários baseados em energia residual, proximidade aos dados, ou capacidades computacionais, com reeleição periódica.