Skip to content

ffx64/optimizing-backend-applications-1

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 

Repository files navigation

🔧 Otimizando Aplicações Back-End - Load Balancer #1

Introdução

O objetivo desta série é projetar uma infraestrutura resiliente, escalável e de alta performance para lidar com aplicações que exigem alta taxa de transações (muitos writes/reads por segundo). Neste post o foco é o balanceamento de carga utilizando Nginx na frente de múltiplas instâncias Spring Boot + Postgres, em ambiente dockerizado. A meta prática: suportar múltiplos serviços concorrentes, além de aplicações web e integrações externas (como bots).

Conceito rápido

Quando falamos de aplicações em produção, não basta apenas “funcionar”, é preciso escala, resiliência e desempenho. Um dos primeiros passos nesse caminho é o uso de load balancers, responsáveis por distribuir requisições entre múltiplos servidores e garantir que nenhum deles se torne um gargalo.

Arquitetura com Docker + Nginx

                                         +---------------------+
                                         |                     |
                          +------------> |     Container 1     |
+-----------------+       |              |                     |
|                 |       |              +---------------------+
|      Nginx      |-------+
|                 |       |              +---------------------+
+-----------------+       |              |                     |
                          +------------> |     Container 2     |
                                         |                     |
                                         +---------------------+

1. Configurando o docker-compose.yml

Na documentação do Docker é possível encontrar recursos que permitem escalar múltiplas instâncias de um mesmo serviço, deixando que o próprio Docker gerencie a distribuição das conexões entre elas. No entanto, o objetivo aqui é entender os fundamentos do balanceamento de carga utilizando diretamente o Nginx como ponto central.

No docker-compose foi configurada a execução de duas instâncias da mesma aplicação. Abaixo segue um exemplo simplificado de como essa configuração foi estruturada:

  • networks: define a rede interna compartilhada entre as instâncias da aplicação e o Nginx. Como apenas o Nginx é exposto externamente, é necessário que todos os containers backend estejam na mesma rede para que o tráfego seja roteado corretamente.
services:
  api_server_a:
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      POSTGRESQL_URL: jdbc:postgresql://postgres:5432/${POSTGRESQL_DATABASE}
      DB_USER: ${POSTGRESQL_USERNAME}
      DB_PASSWORD: ${POSTGRESQL_PASSWORD}
    networks:
      - znet

  api_server_b:
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      DB_URL: jdbc:postgresql://postgres:5432/${POSTGRESQL_DATABASE}
      DB_USER: ${POSTGRESQL_USERNAME}
      DB_PASSWORD: ${POSTGRESQL_PASSWORD}
    networks:
      - znet

  nginx_lb:
    image: nginx:latest
    ports:
      - "8080:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - api_server_a
      - api_server_b
    networks:
      - znet

networks:
  znet:

2. Configurando o nginx.conf

No arquivo nginx.conf foram configurados os hostnames das duas instâncias da aplicação dentro do bloco upstream api_backend.

Importante destacar que apenas o Nginx foi exposto externamente; os containers das APIs permanecem acessíveis apenas pela rede interna.

  • upstream api_backend { ... }: Cria um grupo de servidores backend com o nome api_backend. Esse nome vai ser usado depois no proxy_pass.

  • least_conn;: Estratégia de balanceamento: direcionar a requisição pro servidor que tiver menos conexões ativas.

  • server api-server-a:8080 ...: Diz que o servidor api-server-a (um container no caso) está rodando na porta 8080 e faz parte do pool.

  • max_fails=3: Se o servidor falhar 3 vezes seguidas, o Nginx para de mandar tráfego pra ele temporariamente.

  • fail_timeout=30s: O servidor fica sem receber tráfego por 30 segundos antes do Nginx tentar usá-lo de novo.

  • location / { ... }: Todas as requisições que baterem em / (ou seja, qualquer coisa) vão cair aqui.

events {
  worker_connections 1024;
}

http {
  client_max_body_size 5m;

  upstream api_backend {
    least_conn;
    server api-server-a:8080 max_fails=3 fail_timeout=30s;
    server api-server-b:8080 max_fails=3 fail_timeout=30s;
    keepalive 32;
  }

  server {
    listen 80;

    error_log  /var/log/nginx/error-backend.log warn;
    access_log /var/log/nginx/access-backend.log;

    location / {
      proxy_pass http://api_backend/;
      proxy_set_header Host $host;

      proxy_read_timeout 120s;
      proxy_connect_timeout 5s;
      proxy_send_timeout 30s;
    }
  }
}

Obs: Este é um post introdutório, portanto as configurações apresentadas foram simplificadas para fins de compreensão. É importante destacar que o uso de um Load Balancer contribui para distribuir carga e melhorar a resiliência, mas não resolve, por si só, todos os problemas de performance. Existem outras abordagens de otimização que serão tratadas em publicações futuras.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published