Qual é um método típico para dimensionar um balanceador de carga de software?

22

Costumo ver arquiteturas de aplicativos da web com um SLB / proxy reverso na frente de vários servidores de aplicativos.

O que acontece quando o número de conexões com o SLB requer muitos recursos para um único SLB lidar com eficácia? Para um exemplo concreto, mas exagerado, considere 2 milhões de conexões HTTP persistentes. Claramente, um único SLB não pode lidar com isso.

Qual é a configuração recomendada para escalar a uma SLB?

É típico criar um grupo / cluster de LBs? Em caso afirmativo, como a carga do cliente se espalha entre o grupo de LBs?

z8000
fonte
z8000, você pode dizer qual software de balanceador de carga está usando? Além disso, se possível, qual algoritmo / protocolo ele usa para balanceamento de carga.
Martin
Eu não tenho preferência. Atualizei a pergunta para ficar mais clara.
Z8000 11/11/11
Não está claro para mim por que um balanceador de carga intrinsecamente não pode manipular 2 milhões de conexões HTTP persistentes.
Womble

Respostas:

10

Os balanceadores de carga não podem ser facilmente escalonados por outros balanceadores de carga, pois haverá inerentemente um único balanceador de carga na cadeia em algum lugar mantendo as conexões. Dito isto, balanceadores como LVS ou HAProxy têm capacidade absurda na faixa de Gbps. Depois de ultrapassar os recursos de um único balanceador de carga (software, hardware, o que for), será necessário passar para outras técnicas, como o DNS de rodízio.

Hyppy
fonte
Direita! Ter o único LB é o "problema". Concordo que a taxa de transferência não seria um problema geral. Mas estou preocupado com outros recursos, como RAM, que no meu caso é limitado. Há tantas conexões que podem ser hospedadas em um único SLB antes que a RAM se esgote.
z8000
O HAProxy pode lidar com cerca de 20 a 60 sessões ativas por GB de RAM. Acredito que o LVS pode fazer muito mais, já que os dados retidos da sessão são menores. Se você ficar sem memória RAM, atualize-o ou crie outro balanceador de carga à frente de um sistema DNS round-robin.
Hyppy
1
"Os balanceadores de carga não podem ser facilmente escalonados por outros balanceadores de carga" - na verdade, um único balanceador de carga L4 baseado em ASIC geralmente pode ser colocado na frente de alguns balanceadores de carga baseados em HTTP L7 com excelentes resultados. O mesmo princípio básico se aplica a implementações somente de software, por exemplo, Linux LVS na frente do nignx.
Jesper M
19

OK, já existe uma resposta aceita, mas há algo a acrescentar. As formas 'clássicas' mais comuns de dimensionar a camada do balanceador de carga são (em nenhuma ordem específica):

  • DNS Round Robin para divulgar vários endereços IP do domínio. Para cada endereço IP, implemente um par de servidores altamente disponível (2 servidores cooperando para manter um endereço IP funcionando o tempo todo). Cada IP corresponde a um cluster de balanceador de carga, usando dispositivos ou servidores com software de balanceamento de carga. Escale horizontalmente adicionando mais pares de balanceadores de carga, conforme necessário.

  • Ajustes de roteamento ou firewall para distribuir a carga para vários balanceadores de carga. Faça com que o roteador frontal ou o firewall frontal espalhe as conexões de entrada para vários endereços IP (cada um representando um par do balanceador de carga) fazendo hash no endereço IP de origem , tendo várias rotas de custo igual aos balanceadores de carga ou similares.

  • Uma camada de balanceadores de carga no nível de IP na frente de uma camada de balanceadores de carga no nível HTTP . O balanceamento de carga da camada IP pode ser implementado em ASICs / silício e pode ser prejudicial rapidamente para algumas coisas. Portanto, um único par de balanceador de carga IP pode 'acompanhar' vários balanceadores de carga no nível HTTP / HTTPS e fornecer níveis de desempenho de vários gigabits, mantendo a arquitetura agradável e simples.

Aprofundar-se completamente nas diferentes maneiras de fazer o exposto exigiria uma resposta muito longa. Mas, em geral, não é tão difícil dimensionar a camada do balanceador de carga , é muito mais difícil dimensionar a camada do servidor de aplicativos e, especialmente, a camada do banco de dados.

Se você escolhe um fator de forma de dispositivo (F5, Cisco, A10) ou um servidor genérico (software Windows / Linux +), isso importa menos. As principais considerações ao expandir a camada do balanceador de carga são:

  • Estado completo versus apátrida. Você absolutamente precisa de sessões complicadas ou pode viver sem elas? Não manter o estado torna tudo mais simples.
  • 'Hardware' (ASICs) versus 'software' (servidores de uso geral) para balanceamento de carga. Cada um tem seus prós e contras, consulte a documentação de visão geral do HAProxy vinculada acima.
  • Balanceamento de carga L3 / 4 (IP / TCP / IP) versus balanceamento de carga L7 (HTTP) . Novamente, prós e contras, o documento HAProxy fornece uma boa visão geral.
  • Terminação SSL , onde, nos nós da web ou no balanceador de carga.

Geralmente, você não precisa se preocupar com isso antes que seu site fique muito grande - um único servidor moderno com fx nginx processará dezenas de milhares de solicitações HTTP simples por segundo. Portanto, não faça a otimização prematura, não lide com isso antes que você precise.

Jesper M
fonte
Na verdade, você não precisa que cada endereço IP esteja altamente disponível usando o DNS RR. Os navegadores, em geral, retornam a outro IP, se disponíveis, quando não podem se conectar. Porém, se você tiver serviços públicos da Web, precisará de HA para cada endereço IP, pois muitas bibliotecas de serviços da Web não tratam o failover para outros IPs automaticamente.
rmalayter
9

A chave para escalar uma camada de balanceamento de carga HTTP é adicionar outra camada de balanceamento de carga de nível inferior (IP ou TCP) primeiro. Essa camada pode ser construída inteiramente com software de código aberto, embora você obtenha melhores resultados se tiver roteadores modernos.

Os fluxos (sessões TCP) devem ser hash usando cabeçalhos, como portas IP e TCP de origem / destino, para decidir a qual frontend eles vão. Você também precisa de um mecanismo para garantir que, quando um front-end morre, ele deixa de ser usado.

Existem várias estratégias, vou descrever algumas que usei na produção em sites que atendem a milhões de usuários, para que você possa ter uma idéia. Seria muito longo para explicar tudo em detalhes, mas espero que esta resposta forneça informações / indicadores suficientes para começar. Para implementar essas soluções, você precisará de alguém realmente conhecedor de redes.

É certo que o que estou descrevendo aqui é muito mais difícil de implementar do que o descrito em outras respostas, mas esse é realmente o estado da arte se você tiver um site de alto tráfego com grandes problemas de escalabilidade e requisitos de disponibilidade acima de 99,9% . Desde que você já tenha um engenheiro de rede meio onboard, custa menos configurar e executar (tanto em capex quanto opex) do que os appliances de balanceador de carga e pode ser escalado ainda mais a quase nenhum custo adicional (em comparação com a compra de um novo, ainda mais) aparelho caro quando você supera o modelo atual).

Primeira estratégia: com um firewall

Presumivelmente, você tem alguns roteadores nos quais seus uplinks do ISP estão conectados. Seu ISP fornece 2 links (ativo / passivo, usando VRRP). Nos roteadores, você também usa o VRRP e direciona o tráfego para a rede pública para um firewall. Os firewalls ( FW 1e FW 2abaixo) também são ativos / passivos e filtram o tráfego e enviam cada fluxo para um servidor front-end íntegro (seus balanceadores de carga HTTP FE 1eFE 2 abaixo).

      + -------------- + + -------------- +
      | Roteador ISP A | | Roteador ISP B |
      + -------------- + + -------------- +
             | |
           == # ====================== # == (rede pública)
             | |
      + --------------- + + --------------- +
      | Seu roteador A | | O seu roteador B |
      + --------------- + + --------------- +
             | |
           == # ===== # ========== # ===== # == (rede privada RFC 1918)
             | | | |
       + ------ + + ------ + + ------ + + ------ +
       | FW 1 | FE 1 | FE 2 | FW 2
       + ------ + + ------ + + ------ + + ------ +

O objetivo é ter um fluxo parecido com o seguinte:

  1. O ISP roteia o tráfego que vai dos seus IPs para o seu roteador ativo.
  2. Seus roteadores direcionam o tráfego para um VIP que usa um endereço RFC 1918 . Esse VIP pertence ao firewall ativo, bem como o VRRP. Se você usa o OpenBSD para suas necessidades de firewall, pode usar o CARP , uma alternativa sem patente ao VRRP / HSRP.
  3. Seu firewall aplica o filtro (por exemplo, "apenas permita 80 / tcp e 443 / tcp indo para esse endereço IP específico").
  4. Seu firewall também atua como um roteador e encaminha os pacotes para um front-end saudável.
  5. Seu front-end encerra a conexão TCP.

Agora a mágica acontece nas etapas 4 e 5, então vamos ver em mais detalhes o que eles fazem.

Seu firewall conhece a lista de front-end ( FE 1e FE 2) e seleciona um deles com base em um aspecto específico do fluxo (por exemplo, hash do IP e da porta de origem, entre outros cabeçalhos). Mas ele também precisa garantir que está encaminhando o tráfego para um front-end saudável, caso contrário, você trará um buraco negro. Se você usa o OpenBSD, por exemplo, pode usá-lo relayd. o querelaydo faz é simples: verifica a integridade de todos os seus front-end (por exemplo, enviando-lhes uma solicitação HTTP de análise) e, sempre que um front-end está íntegro, ele é adicionado a uma tabela que o firewall usa para selecionar o próximo salto dos pacotes de um determinado fluxo . Se um frontend falhar nas verificações de integridade, ele será removido da tabela e nenhum pacote será enviado a ele. Ao encaminhar um pacote para um frontend, tudo o que o firewall faz é trocar o endereço MAC de destino do pacote pelo endereço escolhido.

Na etapa 5, os pacotes do usuário são recebidos pelo seu balanceador de carga (seja Varnish, nginx ou qualquer outro). Neste ponto, o pacote ainda está destinado ao seu endereço IP público, portanto, você precisa aliasar seus VIPs na interface de loopback. Isso é chamado DSR (Direct Server Return), porque seus front-ends encerram a conexão TCP e o firewall apenas vê tráfego simplex (apenas pacotes recebidos). Seu roteador encaminhará os pacotes de saída diretamente de volta aos roteadores do ISP. Isso é especialmente bom para o tráfego HTTP, porque as solicitações tendem a ser menores que as respostas, às vezes significativamente. Só para ficar claro: isso não é uma coisa específica do OpenBSD e é amplamente usado em sites de alto tráfego.

Pegadinhas:

  • Os usuários finais se conectarão diretamente aos seus servidores front-end porque você usa o DSR. Talvez já fosse o caso, mas se não, você precisa garantir que eles estejam adequadamente protegidos.
  • Se você usa o OpenBSD, tenha cuidado para que o kernel seja único, pois o desempenho de um único núcleo da CPU limitará a taxa de transferência de um firewall. Pode ser um problema, dependendo do seu tipo de NIC e da taxa de pacotes que você está vendo. Existem maneiras de resolver esse problema (mais sobre isso abaixo).

Segunda estratégia: sem firewall

Essa estratégia é mais eficiente, mas mais difícil de configurar, pois depende mais das especificidades dos roteadores que você possui. A idéia é ignorar o firewall acima e fazer com que os roteadores façam todo o trabalho que os firewalls estavam fazendo.

Você precisará de roteadores que suportem ACLs L3 / L4 por porta, BGP e ECMP e PBR ( Policy Based Routing ). Somente roteadores de ponta oferecem suporte a esses recursos e geralmente possuem taxas de licenciamento extras para usar o BGP. Isso normalmente ainda é mais barato que os balanceadores de carga de hardware e também é muito mais fácil de escalar. O bom desses roteadores de ponta é que eles tendem a ter taxa de linha (por exemplo, eles sempre podem maximizar o link, mesmo em interfaces de 10 GbE, porque todas as decisões que eles tomam são feitas em ASICs em hardware).

Nas portas nas quais você tem uplinks de seu provedor de serviços de Internet, aplique a ACL que costumava estar no firewall (por exemplo, "apenas permita 80 / tcp e 443 / tcp indo para esse endereço IP específico"). Depois, cada um de seus front-end mantém uma sessão BGP com seu roteador. Você pode usar o excelente OpenBGPD (se seus frontends estiverem no OpenBSD) ou Quagga . Seu roteador fará o ECMP do tráfego para os front-end que são íntegros (porque eles estão mantendo as sessões BGP). O roteador também encaminhará o tráfego adequadamente usando o PBR.

Refinamentos

  • Com a solução de par de firewall, é bom se você pode sincronizar os estados TCP entre os firewalls, para que, quando um firewall falhar, tudo falhe suavemente com o outro. Você pode conseguir isso com pfsync.
    • Lembre-se de que pfsyncnormalmente dobrará a taxa de pacotes em seus firewalls.
    • O HTTP é um protocolo sem estado, portanto, não é o fim do mundo se você redefinir todas as conexões durante um failover de firewall porque não o usa pfsync.
  • Se você ultrapassar um único firewall, poderá usar o ECMP no seu roteador para rotear seu tráfego para mais de um par de firewall.
  • Se você usa mais de um par de firewall, também pode torná-los ativos / ativos. Você pode conseguir isso fazendo com que os firewalls mantenham uma sessão BGP com os roteadores, assim como os front-end precisam manter uma no 2º design sem firewalls.

relaydConfiguração de amostra

Veja também HOWTO em https://calomel.org/relayd.html

vip = "1.2.3.4" # Seu endereço IP público
               # (você pode ter mais de um, mas não precisa)
fe1 = "10.1.2.101"
fe2 = "10.1.2.102"
fe3 = "10.1.2.103"
fe4 = "10.1.2.104" # Você pode ter qualquer número de front-ends.
int_if = "em0"
tabela <fe> {$ fe1 tente novamente 2, $ fe2 tente novamente 2, $ fe3 tente novamente 2, $ fe4 tente novamente 2}
tabela <fallback> {127.0.0.1}

redirecionar tráfego da web {
        ouça na porta 80 vip $
        tempo limite da sessão 60
        rota para <fe> verificar http "/healthcheck.html" digest "(o sha1sum de healthcheck.html)" interface $ int_if
}
tsuna
fonte
2

Pessoalmente, eu vou para balanceadores de carga de hardware mais simples e menos configuráveis ​​nesse momento - coisas como ACE / ASAs da Cisco, Foundry ServerIrons, talvez até Zeus ZXTMs (um SW LB projetado para cargas muito pesadas).

Chopper3
fonte
Em outras palavras dimensionar -se ? Esse LB ainda será atingido no máximo em algum número de conexões (etc.). O que então? Essa é realmente a minha pergunta. Obrigado!
Z8000 11/11
1
Sites realmente grandes usam apenas muitos LBs pesados ​​executando sob alguma forma de round-robin DNS - é bom o suficiente para o momento para a maioria e pode lidar com centenas de milhões de conexões. Dito isto, há a questão de por que tantas conexões precisam permanecer abertos, é claro ...
Chopper3
Você quer dizer RRDNS interno ? Legal, eu não pensei nisso. Re: abrir conexões ... Estou explorando opções para um aplicativo que requer o envio de atualizações para clientes conectados ao longo do tempo, pois os eventos ocorrem em algum lugar no back-end. Estou dividido entre um servidor TCP personalizado ou muitas conexões HTTP abertas atrás de um SLB. Obrigado por seus comentários.
Z8000 11/11/11
Eu acho que teria que ser RRDNS externo. Por exemplo, o Twitter.com usaria o RRDNS para resolver e distribuir solicitações a um dos muitos LBs grandes, que distribuiriam a carga aos servidores.
1111 Robert
Sim, Robert, você está certo, por exemplo, usamos as caixas Cisco GSS para fazer RR site a site.
Chopper3
1

Talvez, em vez de manter constantemente tantas conexões abertas para enviar respostas, codifique seu aplicativo de tal maneira que os clientes pesquisem periodicamente seus servidores sempre que necessário.

O que você está fazendo realmente exige uma resposta em milissegundos ou um cliente pode esperar 15/20 segundos até o próximo período de pesquisa?

Mxx
fonte
0

Uma abordagem típica seria criar um cluster grande o suficiente para lidar com a carga necessária e usar um SLB que possa fazer um balanceamento determinístico de carga (no caso de conexões persistentes).

Algo como o CARP usa um hash do IP solicitante para determinar qual servidor da web de back-end lidaria com a solicitação; isso deve ser determinístico, mas não muito útil se houver um firewall ou NAT na frente do seu balanceador de carga.
Você também pode encontrar algo como IPVS útil se estiver executando no Linux.

Martin
fonte
O que você diz sobre a carpa está tão longe de como funciona, eu não saberia por onde começar! + -0 por mencionar IPVS.
3molo 12/05
@ 3molo ... hein? consulte net.inet.carp.arpbalance em linux.com/archive/feed/35482 "..CARP source-hashes o IP de origem de uma solicitação. O hash é então usado para selecionar um host virtual do pool disponível para lidar com a solicitação . "
Paul