ASP.NET Core 2.2: implementando Load Balancing com Nginx, Docker e Docker Compose

Renato Groffe
Jan 2 · 5 min read

Uma das soluções mais populares de proxy reverso, o Nginx é um projeto open source que em muito facilita a implementação de mecanismos como load balancing, compressão de dados e segurança quando utilizado em conjunto com aplicações Web construídas nas mais variadas plataformas.

O suporte a Docker é outra característica que pesa a favor na adoção deste projeto, possibilitando assim a montagem de ambientes que dependam do Nginx de forma rápida e descomplicada.

Neste artigo demonstrarei o uso do Nginx na definição de um Load Balancer sem grandes esforços de configuração. O objetivo com isto será distribuir a carga de processamento entre 3 instâncias de uma API REST construída com o ASP.NET Core 2.2, empregando ainda containers Docker e o Docker Compose em tal tarefa.


Detalhes sobre a aplicação Web a ser utilizada

A aplicação Web utilizada neste artigo já foi descrita em outros posts que publiquei anteriormente. Trata-se de uma API REST que funciona como um contador, o qual será incrementado a cada requisição HTTP recebida. Este exemplo foi convertido recentemente para o ASP.NET Core 2.2 e detalhado no seguinte artigo:

ASP.NET Core 2.2 + Docker: visão geral e exemplos

Uma imagem de tal projeto foi publicada no Docker Hub como renatogroffe/apicontagem-sdk-2–2, podendo ser baixada e utilizada sem maiores dificuldades.

O projeto com todo o código-fonte também está no GitHub:

https://github.com/renatogroffe/ASP.NET-Core-2.2_API_Docker-Compose

Todos os testes realizados neste artigo aconteceram em uma máquina na qual foi instalado o Ubuntu 18.04 Desktop.


Implementando o Load Balancer com Nginx, Docker e Docker Compose

Serão abordadas primeiramente nesta seção as definições do arquivo docker-compose.yml:

  • Uma imagem baseada no Nginx e chamada apicontagem-nginx será criada, com o arquivo Dockerfile contendo as definições necessárias e estando localizado no mesmo diretório de docker-compose.yml;
  • Tal imagem servirá de base para a criação do container proxy, sendo que na mesma estarão ainda configurações do Load Balancer;
  • Os containers apicontagem01, apicontagem02 e apicontagem03 serão gerados com base na imagem renatogroffe/apicontagem-sdk-2–2. Cada um destes foi configurado para execução numa porta diferente (20001, 20002 e 20003);
  • Será o container proxy que receberá solicitações HTTP e distribuirá a carga de processamento entre os 3 containers correspondentes às instâncias da API REST de contagem;
  • Todos os containers indicados em docker-compose.yml fazem parte de uma mesma network (apicontagem-network). O uso deste recurso do Docker Compose permite que o container proxy possa referenciar os outros 3 pelo nome, dispensando assim o uso de IPs e portas em arquivos de configuração (o que representa uma grande vantagem, já que mudanças neste sentido costumam acontecer na passagem de um ambiente para outro).

Quanto ao nginx.conf, neste arquivo ficarão as configurações de load balancing conforme indicado na próxima listagem:

  • Em upstream foi definido um item chamado apicontagem e estão indicados como servidores os containers apicontagem01, apicontagem02 e apicontagem03 (vale destacar que graças ao Docker Compose não foi necessário referenciar aqui IP ou porta, simplesmente o nome dos containers);
  • O uso do parâmetro least_conn permite que uma requisição seja enviada ao servidor/container com o menor número de conexões ativas. Existem outras possibilidades e regras em termos de balanceamento de carga; para saber mais a respeito das mesmas acesse o link disponibilizado na seção de Referências;
  • Em server a instrução listen 80; corresponde à porta default na qual o Nginx receberá requisições (a porta em que realmente acontecerá o envio de solicitações HTTP no host que hospeda os containers foi indicada no arquivo docker-compose.yml);
  • No item location de server foi especificado o redirecionamento, com a instrução proxy_pass referenciando o item apicontagem (no qual constam declaradas as diferentes instâncias da API REST).

Já no arquivo Dockerfile estão as instruções para a construção de uma imagem baseada no Nginx e contendo as configurações de load balancing especificadas em nginx.conf:

  • Na cláusula FROM foi indicada a imagem do nginx, a qual servirá de base para a geração da nova imagem;
  • Por default o acesso acontecerá na porta 80 como determinado em EXPOSE (na criação do container por meio do docker-compose.yml será feito o mapeamento para a porta 20000 do host);
  • O arquivo nginx.conf original será removido via comando RUN, com a substituição de tal item pelo arquivo de mesmo nome descrito nesta seção (a partir da instrução COPY).

A execução do comando docker-compose up -d no diretório em que se encontram os arquivos docker-compose.yml, nginx.conf e Dockerfile terá como resultados:

  • A geração da imagem apicontagem-nginx, base para a criação do container que efetuará o load balancing;
  • Os 4 containers já mencionados serão gerados e entrarão em modo de execução, com os mesmos estando vinculados à network apicontagem-network.

O comando docker network ls mostrará que a rede apicontagem-network foi criada com sucesso (como loadbalancernginx_apicontagem-network, resultado da concatenação com o nome do diretório em que se encontra o arquivo docker-compose.yml):

A instrução docker-compose ps listará os containers gerados como resultado deste processo:

Também aparecerão via comando docker ps os novos containers:


Testes

A execução de testes via Firefox, Postman e curl a partir do Terminal mostrará que o Load Balancer foi devidamente configurado, com os resultados produzidos indicando o correto redirecionamento para os 3 diferentes containers/instâncias da API REST (os valores de machineName diferem em cada caso):

A execução do comando curl http://localhost:20000/api/contador?[1-9] -w “\n” no Terminal enviará 9 requisições e exibirá seus respectivos resultados em sequência, comprovando novamente o funcionamento do Load Balancer:


Renato Groffe

Written by

Microsoft Most Valuable Professional (MVP), Multi-Plataform Technical Audience Contributor (MTAC), Software Engineer, Technical Writer and Speaker