Qual è un metodo tipico per ridimensionare un bilanciamento del carico del software?


22

Vedo spesso architetture di app Web con SLB / proxy inverso di fronte a un gruppo di server di app.

Cosa succede quando il numero di connessioni allo SLB richiede troppe risorse per un singolo SLB per essere gestito in modo efficace? Per un esempio concreto ma esagerato, considera 2 milioni di connessioni HTTP persistenti. Chiaramente un singolo SLB non può gestirlo.

Qual è la configurazione consigliata per scalare fuori una SLB?

È tipico creare un gruppo / cluster di LB? In tal caso, come viene distribuito il carico del client tra il gruppo di LB?


z8000, puoi dire quale bilanciamento del carico software stai usando? Inoltre, se possibile, quale algoritmo / protocollo utilizza per il bilanciamento del carico.
Martin,

Non ho preferenze Ho aggiornato la domanda per essere più chiara.
z8000,

Non mi è chiaro perché un bilanciamento del carico non possa intrinsecamente gestire 2 milioni di connessioni HTTP persistenti.
Womble

Risposte:


10

I sistemi di bilanciamento del carico non possono essere facilmente ridimensionati da altri sistemi di bilanciamento del carico, in quanto da qualche parte sulla catena sarà intrinsecamente presente un unico sistema di bilanciamento del carico che mantiene le connessioni. Detto questo, i bilanciatori come LVS o HAProxy hanno una capacità assurda nella gamma Gbps. Una volta superate le capacità di un singolo bilanciamento del carico (software, hardware o altro), dovrai passare ad altre tecniche come il DNS round robin.


Destra! Avere il singolo LB è il "problema". Concordo sul fatto che la velocità effettiva non sarebbe un problema in generale. Ma sono preoccupato per altre risorse come la RAM, che nel mio caso è limitata. Esistono solo così tante connessioni che possono essere ospitate su un singolo SLB prima che la RAM si esaurisca.
z8000,

HAProxy può gestire circa 20k-60k sessioni attive per GB di RAM. Credo che LVS possa fare molto di più, poiché i dati della sessione conservata sono più piccoli. Se si esaurisce la RAM, aggiornarla o creare un altro bilanciamento del carico supportato da un sistema DNS round robin.
Hyppy,

1
"I sistemi di bilanciamento del carico non possono essere facilmente ridimensionati da altri sistemi di bilanciamento del carico": in realtà, un singolo sistema di bilanciamento del carico L4 basato su ASIC può spesso essere posizionato di fronte a un paio di sistemi di bilanciamento del carico basati su HTTP L7 con risultati eccellenti. Lo stesso principio di base si applica alle implementazioni solo software, ad esempio Linux LVS davanti a nignx.
Jesper M,

19

OK, c'è già una risposta accettata, ma c'è qualcosa da aggiungere. I modi 'classici' più comuni per ridimensionare il livello del bilanciamento del carico sono (in nessun ordine particolare):

  • DNS Round Robin per pubblicizzare più indirizzi IP per il dominio. Per ogni indirizzo IP, implementare una coppia di server a disponibilità elevata (2 server che cooperano per mantenere sempre attivo un indirizzo IP). Ogni IP corrisponde a un cluster di bilanciamento del carico, utilizzando dispositivi o server con software di bilanciamento del carico. Ridimensionare orizzontalmente aggiungendo più coppie di bilanciamento del carico secondo necessità.

  • Modifiche al routing o al firewall per distribuire il carico a più bilanciatori del carico. Chiedi al router anteriore o al firewall anteriore di diffondere le connessioni in entrata su più indirizzi IP (ognuno dei quali rappresenta una coppia di bilanciamento del carico) eseguendo l'hashing dell'indirizzo IP di origine , avendo più percorsi di uguale costo verso i bilanciatori di carico o simili.

  • Un livello di bilanciamento del carico a livello IP davanti a un livello di bilanciamento del carico a livello HTTP . Il bilanciamento del carico a livello IP può essere implementato in ASIC / silicio e può essere risolto rapidamente per alcune cose. Pertanto, una singola coppia di bilanciamento del carico IP può spesso "tenere il passo" con diversi bilanciatori di carico di livello HTTP / HTTPS e fornire livelli di prestazioni multi-gigabit mantenendo l'architettura semplice e piacevole.

Andare completamente in profondità sui diversi modi di fare quanto sopra richiederebbe una risposta molto lunga. Ma in generale, non è così difficile ridimensionare il livello di bilanciamento del carico , è molto più difficile ridimensionare il livello del server delle applicazioni e in particolare il livello del database.

Sia che si scelga un fattore di forma dell'appliance (F5, Cisco, A10) o un server generico (Windows / Linux + software) è meno importante. Le principali considerazioni per ridimensionare il livello di bilanciamento del carico sono:

  • Stato pieno contro apolide. Hai assolutamente bisogno di sessioni appiccicose o puoi vivere senza? Non mantenere lo stato rende tutto più semplice.
  • 'Hardware' (ASIC) contro 'software' (server per scopi generici) per il bilanciamento del carico. Ognuno ha i suoi pro e contro, vedere la documentazione panoramica HAProxy collegata sopra.
  • Bilanciamento del carico L3 / 4 (IP / TCP / IP) rispetto al bilanciamento del carico L7 (HTTP) . Ancora una volta, pro e contro, il documento HAProxy offre una buona panoramica.
  • Terminazione SSL , dove, sui webnodes o sul bilanciamento del carico.

In generale, non devi preoccuparti di questo prima che il tuo sito Web diventi molto grande: un singolo server moderno con fx nginx gestirà decine di migliaia di semplici richieste HTTP al secondo. Quindi non fare l'ottimizzazione prematura, non occuparti di questo prima che tu debba farlo.


In realtà non è necessario che ciascun indirizzo IP sia altamente disponibile utilizzando DNS RR. I browser, in generale, torneranno a un altro IP se disponibile quando non possono connettersi. Tuttavia, se si dispone di servizi Web pubblici, sarà necessario HA per ciascun indirizzo IP, poiché molte librerie di servizi Web non gestiranno automaticamente il failover su altri IP.
rmalayter,

9

La chiave per ridimensionare un livello di bilanciamento del carico HTTP è aggiungere prima un altro livello di bilanciamento del carico di livello inferiore (IP o TCP). Questo livello può essere costruito interamente con software open source, sebbene otterrai risultati migliori se disponi di router moderni.

I flussi (sessioni TCP) devono essere sottoposti a hash usando intestazioni come porte IP e TCP di origine / destinazione, per decidere a quale frontend vanno. È inoltre necessario un meccanismo per assicurarsi che quando un frontend muore, smette di abituarsi.

Esistono varie strategie, ho intenzione di delineare un paio che ho usato in produzione su siti che servono milioni di utenti, in modo da poter avere l'idea. Sarebbe troppo lungo per spiegare tutto nei dettagli, ma spero che questa risposta ti dia abbastanza informazioni / indicazioni per iniziare. Per implementare queste soluzioni avrai bisogno di qualcuno che sia veramente ben informato sulla rete.

È vero che ciò che sto descrivendo qui è molto più difficile da implementare rispetto a quanto descritto in altre risposte, ma questo è davvero lo stato dell'arte se si dispone di un sito Web a traffico elevato con grandi problemi di scalabilità e requisiti di disponibilità superiori al 99,9% . A condizione che tu abbia già un ingegnere di rete un po 'a bordo, costa meno per l'installazione e l'esecuzione (sia in capex che in opex) rispetto agli apparecchi di bilanciamento del carico e può essere ulteriormente ridimensionato senza costi aggiuntivi (rispetto all'acquisto di un nuovo, ancora di più apparecchio costoso quando si supera il modello attuale).

Prima strategia: con un firewall

Presumibilmente hai un paio di router su cui sono collegati i tuoi uplink ISP. L'ISP fornisce 2 collegamenti (attivo / passivo, utilizzando VRRP). Sui router, usi anche VRRP e instrada il traffico diretto alla tua rete pubblica verso un firewall. Anche i firewall ( FW 1e FW 2inferiori) sono attivi / passivi e filtrano il traffico e inviano ciascun flusso a un server frontend integro (i bilanciatori del carico HTTP FE 1e FE 2inferiori).

      + -------------- + + -------------- +
      | Router ISP A | | Router ISP B |
      + -------------- + + -------------- +
             | |
           == # ====================== # == (rete pubblica)
             | |
      + --------------- + + --------------- +
      | Il tuo router A | | Il tuo router B |
      + --------------- + + --------------- +
             | |
           == # ===== # ========== # ===== # == (rete privata RFC 1918)
             | | | |
       + ------ + + ------ + + ------ + + ------ +
       | AI 1 | | FE 1 | | FE 2 | | AI 2 |
       + ------ + + ------ + + ------ + + ------ +

L'obiettivo è avere un flusso simile al seguente:

  1. L'ISP indirizza il traffico diretto ai tuoi IP verso il tuo router attivo.
  2. I router indirizzano il traffico a un VIP che utilizza un indirizzo RFC 1918 . Questo VIP è di proprietà del firewall attivo, proprio come VRRP. Se usi OpenBSD per le tue esigenze di firewall, puoi usare CARP , un'alternativa senza brevetti a VRRP / HSRP.
  3. Il tuo firewall applica il filtro (es. "Consenti solo 80 / tcp e 443 / tcp andando a questo particolare indirizzo IP").
  4. Il firewall funge anche da router e inoltra i pacchetti a un frontend sano.
  5. Il frontend termina la connessione TCP.

Ora la magia avviene nei passaggi 4 e 5, quindi vediamo più in dettaglio cosa fanno.

Il tuo firewall conosce l'elenco dei frontend ( FE 1e FE 2) e ne sceglierà uno in base a un aspetto particolare del flusso (ad es. Eseguendo l'hashing dell'IP e della porta di origine, tra le altre intestazioni). Ma deve anche assicurarsi che inoltri il traffico a un frontend sano, altrimenti si creerà un blackhole. Se usi OpenBSD, ad esempio, puoi usare relayd. Che cosarelaydfa è semplice: controlla l'integrità di tutti i tuoi frontend (ad esempio inviando loro una richiesta HTTP probe) e ogni volta che un frontend è integro lo aggiunge a una tabella che il firewall utilizza per selezionare l'hop successivo dei pacchetti di un determinato flusso . Se un frontend non supera i controlli di integrità, viene rimosso dalla tabella e non viene più inviato alcun pacchetto. Quando si inoltra un pacchetto a un frontend, tutto il firewall non fa altro che scambiare l'indirizzo MAC di destinazione del pacchetto con quello del frontend scelto.

Nel passaggio 5, i pacchetti dell'utente vengono ricevuti dal bilanciamento del carico (che si tratti di vernice, nginx o altro). A questo punto, il pacchetto è ancora destinato al tuo indirizzo IP pubblico, quindi devi alias i tuoi VIP sull'interfaccia di loopback. Questo si chiama DSR (Direct Server Return), perché i front-end terminano la connessione TCP e il firewall in mezzo vede solo il traffico simplex (solo pacchetti in entrata). Il router instraderà i pacchetti in uscita direttamente ai router dell'ISP. Ciò è particolarmente utile per il traffico HTTP perché le richieste tendono ad essere più piccole delle risposte, a volte in modo significativo. Giusto per essere chiari: questa non è una cosa specifica di OpenBSD ed è ampiamente usata nei siti Web ad alto traffico.

grattacapi:

  • Gli utenti finali si collegheranno direttamente ai server frontend perché si utilizza DSR. Forse era già il caso, ma in caso contrario, è necessario assicurarsi che siano adeguatamente protetti.
  • Se usi OpenBSD, fai attenzione che il kernel è a thread singolo, quindi le prestazioni di un singolo core della CPU limiteranno il throughput di un firewall. Potrebbe essere un problema a seconda del tipo di scheda NIC e della frequenza dei pacchetti che stai vedendo. Esistono modi per risolvere questo problema (ulteriori informazioni qui di seguito).

Seconda strategia: senza firewall

Questa strategia è più efficiente ma più difficile da configurare perché dipende più dalle specifiche dei router che hai. L'idea è di bypassare il firewall sopra e far eseguire ai router tutto il lavoro svolto dai firewall.

Avrai bisogno di router che supportino ACL L3 / L4 per porta, BGP ed ECMP e Policy Based Routing (PBR). Solo i router di fascia alta supportano queste funzionalità e spesso hanno costi di licenza aggiuntivi per utilizzare BGP. Questo è in genere ancora più economico dei sistemi di bilanciamento del carico hardware ed è anche molto più facile da scalare. La cosa positiva di questi router di fascia alta è che tendono ad essere a velocità di linea (ad esempio, possono sempre massimizzare il collegamento, anche su interfacce 10GbE, perché tutte le decisioni che prendono vengono prese in hardware dagli ASIC).

Sulle porte su cui hai i tuoi uplink ISP, applica l'ACL che era sul firewall (ad esempio "consenti solo a 80 / tcp e 443 / tcp di andare a questo particolare indirizzo IP"). Quindi fai in modo che ognuno dei tuoi frontend mantenga una sessione BGP con il tuo router. Puoi usare l'eccellente OpenBGPD (se i tuoi frontend sono su OpenBSD) o Quagga . Il tuo router ECMP il traffico verso i front-end che sono sani (perché mantengono le loro sessioni BGP). Il router indirizzerà inoltre il traffico in modo appropriato utilizzando PBR.

perfezionamenti

  • Con la soluzione di accoppiamento firewall, è bello poter sincronizzare gli stati TCP tra i firewall, in modo che quando un firewall si guasta, tutto si interrompe senza problemi con l'altro. Puoi farlo con pfsync.
    • Tieni presente che pfsyncin genere raddoppierà la velocità dei pacchetti sui tuoi firewall.
    • HTTP è un protocollo senza stato, quindi non è la fine del mondo se si ripristinano tutte le connessioni durante un failover del firewall perché non si utilizza pfsync.
  • Se si supera un singolo firewall, è possibile utilizzare ECMP sul router per indirizzare il traffico a più di una coppia di firewall.
  • Se usi più di una coppia di firewall, potresti anche renderli tutti attivi / attivi. È possibile ottenere ciò facendo in modo che i firewall mantengano una sessione BGP con i router, proprio come i frontend devono mantenerne uno nel 2o progetto senza firewall.

relaydConfig. Campione

Vedi anche HOWTO su https://calomel.org/relayd.html

vip = "1.2.3.4" # Il tuo indirizzo IP pubblico
               # (puoi averne più di uno, ma non è necessario)
fe1 = "10.1.2.101"
Fe2 = "10.1.2.102"
Fe3 = "10.1.2.103"
fe4 = "10.1.2.104" # Puoi avere un numero qualsiasi di frontend.
int_if = "em0"
tabella <fe> {$ fe1 riprovare 2, $ fe2 riprovare 2, $ fe3 riprovare 2, $ fe4 riprovare 2}
tabella <fallback> {127.0.0.1}

reindirizzare webtraffic {
        ascolta su $ vip port 80
        timeout della sessione 60
        percorso a <fe> controlla http "/healthcheck.html" digest "(il sha1sum di healthcheck.html)" interfaccia $ int_if
}

2

Personalmente vado a bilanciatori del carico hardware più semplici e meno configurabili a quel punto - cose come gli ACE / ASA di Cisco, gli Foundry ServerIrons, forse anche Zeus ZXTM (un LB SW progettato per carichi molto pesanti).


In altre parole scalare fino ? Tale LB verrà comunque raggiunto al massimo in un numero di connessioni (ecc.). Cosa poi? Questa è davvero la mia domanda. Grazie!
z8000,

1
I siti veramente grandi usano solo molti LB pesanti che funzionano sotto una qualche forma di round robin DNS: per il momento è abbastanza buono per molti e può gestire centinaia di milioni di connessioni. Detto questo, c'è la domanda sul perché così tante connessioni debbano rimanere aperte ovviamente ...
Chopper3,

È che interni RRDNS vuoi dire? Bene, non ci ho pensato. Ri: apri connessioni ... Sto esplorando le opzioni per un'app che richiede l'invio di aggiornamenti ai client connessi nel tempo poiché gli eventi si verificano da qualche parte nel back-end. Sono diviso tra un server TCP personalizzato o molte connessioni HTTP aperte dietro uno SLB. Grazie per i vostri commenti.
z8000,

Penso che dovrebbe essere RRDNS esterno. Ad esempio, Twitter.com userebbe RRDNS per risolvere e distribuire le richieste a uno dei molti LB di grandi dimensioni che distribuiscono quindi il carico ai server.
Robert,

Sì, Robert, hai ragione, ad esempio usiamo i box Cisco GSS per fare RR sito per sito.
Chopper3,

1

Forse invece di mantenere costantemente così tante connessioni aperte per inviare risposte, codificare l'applicazione in modo tale che i client eseguano periodicamente il polling dei server tutte le volte che è necessario?

Qualunque cosa tu stia facendo, in realtà richiede una risposta in questo millisecondo o un cliente può attendere 15/20 secondi fino al prossimo periodo di polling?


0

Un approccio tipico sarebbe quello di creare un cluster abbastanza grande da gestire il carico richiesto e utilizzare uno SLB in grado di eseguire un bilanciamento del carico deterministico (nel caso di connessioni persistenti).

Qualcosa come CARP usa un hash dell'IP richiedente per determinare quale server web back-end gestirà la richiesta, questo dovrebbe essere deterministico ma non molto utile se c'è un firewall o NAT davanti al bilanciamento del carico.
Potresti anche trovare utile qualcosa come IPVS se sei in esecuzione su Linux.


Quello che dici delle carpe è così lontano da come funziona, non saprei da dove cominciare! + -0 per menzionare IPVS.
3molo,

@ 3molo ... eh? vedi net.inet.carp.arpbalance su linux.com/archive/feed/35482 "..CARP source-hash l'IP di origine di una richiesta. L'hash viene quindi usato per selezionare un host virtuale dal pool disponibile per gestire la richiesta ".
Paul,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.