Este repositório é o trabalho final da disciplina de Sistemas Operacionais 2026.1.
O projeto implementa e avalia algoritmos de escalonamento e balanceamento de carga em um ambiente distribuído com orquestração de contêineres. A proposta é correlacionar, na prática, os conceitos vistos na disciplina de Sistemas Operacionais com o problema de decisão de qual servidor deve receber cada requisição em um sistema distribuído.
Ao longo da implementação, o projeto faz uso intenso de:
- virtualização com contêineres Docker;
- orquestração com Docker Swarm e Kubernetes;
- multithreading;
- controle de concorrência com
locks.
O sistema é composto por três partes principais:
http_load_balancerhttp_target_discoverysample_app
O fluxo geral funciona assim:
- O
http_target_discoverydescobre quais instâncias estão saudáveis e disponíveis. - Ele envia a lista de alvos para o
http_load_balancer. - O
http_load_balancerrecebe as requisições HTTP na porta pública e decide, de acordo com o algoritmo configurado, para qual target encaminhá-las. - O
sample_appresponde às requisições e serve como aplicação de teste para observação do comportamento dos algoritmos.
É o proxy reverso do projeto. Ele expõe:
- porta
8080para tráfego externo; - porta
9090para a API interna de gerenciamento.
Ele mantém em memória:
- a lista atual de targets;
- a estratégia de escalonamento selecionada;
- estatísticas por target, como número de conexões e tempo de resposta.
É o serviço responsável por descobrir os targets ativos e sincronizar o estado com o balanceador.
Ele suporta dois provedores:
- Docker;
- Kubernetes.
E dois modos de rede:
internal;published;both.
É uma aplicação Flask simples usada para carga e validação. Ela expõe:
GET /GET /infoGET /health
O balanceador implementa os seguintes algoritmos:
round_robinweighted_round_robinip_hashsticky_round_robin
least_connectionsleast_response_time
round_robin: distribui as requisições ciclicamente entre os targets.weighted_round_robin: distribui proporcionalmente ao peso de cada target.ip_hash: usa o IP do cliente para produzir um hash e escolher sempre o mesmo target para o mesmo cliente, quando possível.sticky_round_robin: mantém um mapeamento persistente entre cliente e target, preservando afinidade por IP.least_connections: envia a requisição para o target com menos conexões ativas.least_response_time: escolhe o target com menor tempo de resposta registrado.
O projeto usa multithreading em pontos centrais do sistema:
- cada conexão TCP aceita pelo servidor é tratada em uma thread separada;
- a leitura e atualização de estados compartilhados é protegida com
locks; - o discovery roda em um agendador periódico para sincronizar os alvos sem bloquear o balanceador;
- as estatísticas dos targets são atualizadas de forma segura em memória.
Isso permite discutir, na prática, tópicos clássicos de Sistemas Operacionais como:
- concorrência;
- sincronização;
- exclusão mútua;
- uso eficiente de recursos;
- isolamento por contêineres;
- escalabilidade em ambientes distribuídos.
packages/http_load_balancer: implementação do balanceador.packages/http_target_discovery: descoberta e sincronização dos targets.packages/sample_app: aplicação de exemplo.k8s/: manifests para Kubernetes.kind/: cluster local para testes com Kind.compose.yaml: base para execução em Docker Swarm / Compose.scripts/hammer_load_balancer.py: script simples de geração de carga.docs/: documentação e material de apoio.
- Python
3.14 uv- Docker
- Docker Compose ou Docker Swarm
- Kubernetes
kindekubectlpara o ambiente local de cluster
make installOu diretamente:
uv sync --all-groups --all-packagesmake http-load-balancerOu:
uv run python -m http_load_balancermake http-target-discoveryOu:
uv run python -m http_target_discoveryuv run python -m sample_appOs serviços usam variáveis de ambiente com prefixos próprios.
Prefixo: LB_
Principais variáveis:
LB_HOST- host de bind, padrão0.0.0.0LB_PROXY_PORT- porta pública, padrão8080LB_INTERNAL_PORT- porta interna, padrão9090LB_BUFFER_SIZE- tamanho do buffer TCP, padrão4096LB_BACKLOG- backlog da fila de conexões, padrão128
O balanceador persiste o estado de rotacionamento em settings/routing.yaml.
Prefixo: DISCOVERY_
Principais variáveis:
DISCOVERY_PROVIDER_STRATEGY-dockeroukubernetesDISCOVERY_NETWORK_STRATEGY-internal,publishedoubothDISCOVERY_LB_TARGETS_URL- endpoint interno do balanceador, por exemplohttp://http-load-balancer-internal:9090/targetsDISCOVERY_POLL_INTERVAL_SECONDS- intervalo de sincronização, padrão5DISCOVERY_REQUEST_TIMEOUT_SECONDS- timeout das requisições HTTP, padrão5DISCOVERY_DOCKER_TARGET_LABEL- label usada para descobrir containers Docker, padrãohttp-load-balancer.targetDISCOVERY_KUBERNETES_DEPLOYMENT_NAME- nome do deployment observado no KubernetesDISCOVERY_KUBERNETES_DEPLOYMENT_APP_NAME- nome do app observado no KubernetesDISCOVERY_KUBERNETES_NAMESPACE- namespace observado, padrãodefault
- O servidor de proxy recebe a conexão na porta
8080. - O request é lido manualmente via socket.
- O algoritmo atual escolhe o target de acordo com a estratégia configurada.
- A requisição é encaminhada ao target escolhido.
- A resposta é repassada de volta ao cliente.
- As estatísticas do target são atualizadas.
- O discovery consulta o provedor escolhido.
- Ele identifica targets saudáveis e ativos.
- Ele compara o snapshot atual com o último estado enviado.
- Se houver mudança, sincroniza os targets via API interna do balanceador.
O provider Docker busca containers com a label http-load-balancer.target=true, filtra apenas os que estão saudáveis e suporta descoberta por:
- IP interno do container;
- porta publicada;
- ambos, dependendo da estratégia de rede.
O provider Kubernetes observa:
Deployment;ReplicaSet;Pod.
Ele considera apenas pods em estado Running e Ready, e descobre alvos por:
- IP do pod e porta do container;
- IP do nó e
hostPort, quando aplicável.
O repositório contém manifests em k8s/ para:
http_load_balancerhttp_target_discoverysample_app
bash kind/setup.shIsso cria ou reaproveita o cluster definido em kind/config.yaml, exporta o kubeconfig e instala metrics-server, necessário para o HorizontalPodAutoscaler.
kubectl apply -k k8s/http-load-balancerexposto emNodePortna porta30080http-load-balancer-internalexposto internamente na porta9090http-target-discoverycom permissões para consultarDeployment,ReplicaSetePodsample-appcomreadinessProbe,livenessProbeeHPA
O arquivo compose.yaml descreve a base usada para orquestração com contêineres e replica a aplicação de teste com deploy.replicas.
Em um ambiente compatível com Swarm, a ideia é publicar as imagens e orquestrar os serviços a partir desse manifesto, preservando a lógica de descoberta e balanceamento do projeto.
O script scripts/hammer_load_balancer.py faz uma carga simples contra o balanceador na URL padrão http://127.0.0.1:30080.
Execução:
python scripts/hammer_load_balancer.pyEle dispara múltiplos workers em paralelo e contabiliza sucesso e falhas.
GET /targetsPUT /targetsPOST /targets/reloadGET /targets/statsPUT /targets/stats
GET /GET /infoGET /health
- O projeto foi organizado como workspace com
uv. - Cada pacote possui seu próprio
pyproject.tomle seu próprio ponto de entrada. - O código foi pensado para facilitar experimentos com escalonamento, afinidade, estatísticas de execução e comportamento sob concorrência.