Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Configurazione: load balancer TCP e UDP

Tutorial per imparare l'uso di nginx come load balancer di applicazioni TCP e UDP, al fine di ottimizzare l'uso delle risorse del server.
Tutorial per imparare l'uso di nginx come load balancer di applicazioni TCP e UDP, al fine di ottimizzare l'uso delle risorse del server.
Link copiato negli appunti

Nella modalità di load balancing HTTP il server Nginx opera a livello applicativo, interpretando le richieste HTTP in arrivo dai client e reindirizzandole ai server applicativi secondo la configurazione stabilita. Questa modalità viene definita Layer 7 load balancing, poiché nello stack ISO/OSI il livello 7 è appunto quello applicativo.

Nginx può operare come load balancer ad un livello più basso rispetto quello applicativo, ed in particolare a livello di trasporto. Questa modalità viene spesso definita Level 4 load balancing, riferendosi nuovamente allo stack ISO/OSI. In questa modalità, il server non opera più su richieste, ma su generici flussi di dati detti stream.

In altre parole, a differenza del load balancing di livello applicativo, nel load balancing di livello 4 il server è ignaro del contenuto dei messaggi scambiati tra client e server e del loro significato, e si limita semplicemente a reindirizzare i flussi opportunamente.

Nginx può operare sia su connessioni TCP che su datagrammi UDP, reindirizzandoli opportunamente ai server in upstream.

Configurazione

Come nel caso del load balancing HTTP, la configurazione avviene mediante la specifica dei server applicativi con l'aggiunta della direttiva upstream e con la configurazione del server in ingresso con la direttiva server. Tuttavia, a differenza del load balancing HTTP, queste direttive andranno inserite nel blocco stream invece che nel blocco http. Ad esempio, supponendo di voler distribuire il carico di tre server DNS, una tipica configurazione potrebbe essere la seguente:

stream {
    upstream dns_servers {
        server ns1.miaapp.com:53;
        server ns2.miaapp.com:53;
        server ns3.miaapp.com:53;
    }
    server {
        listen 53 udp;
        proxy_pass dns_servers;
    }
}

Per impostazione predefinita, il server si metterà in ascolto sulla porta 53 UDP su tutte le interfacce di rete presenti nella macchina. Nel caso in cui si volesse restringere il binding ad un'interfaccia specifica, è possibile utilizzare la direttiva proxy_bind, specificando l'indirizzo IP dell'interfaccia da usare. Ad esempio, per effettuare il binding solo sull'interfaccia di loopback, è sufficiente specificare l'indirizzo del localhost, come mostrato nell'esempio seguente:

stream {
    upstream dns_servers {
        server ns1.miaapp.com:53;
        server ns2.miaapp.com:53;
        server ns3.miaapp.com:53;
    }
    server {
        listen 127.0.0.1:53 udp;
        proxy_pass dns_servers;
        proxy_bind 127.0.0.1:53;
    }
}

Inoltre, è possibile controllare la dimensione del buffer utilizzato da Nginx per mantenere in memoria i dati in transito da e verso i client utilizzando la direttiva proxy_buffer_size. Ad esempio, per impostare il buffer ad una dimensione di 16 KB è sufficiente aggiungere la direttiva proxy_buffer_size nel blocco server con il valore 16k:

stream {
    # ...
    server {
        listen 8080;
        proxy_pass my_servers;
        proxy_buffer_size 16k;
    }
}

Diminuire la dimensione del buffer può essere utile per ridurre la latenza introdotta dal load balancer, ma può comportare un aumento del numero di operazioni di I/O effettuate dal server, con un conseguente aumento del carico. Una dimensione ottimale va ricercata in relazione con il particolare caso d'uso, tenendo conto della dimensione media dei pacchetti in transito e delle esigenze in termini di latenza.

Metodi di load balancing

Anche in modalità TCP / UDP, Nginx supporta diversi metodi per la selezione del server di upstream al quale reindirizzare i flussi in ingresso.

  • round-robin - La modalità di default. I server vengono selezionati secondo una sequenza ciclica, in base all'ordine delle connessioni dei client;
  • least-conn - Viene selezionato il server con meno connessioni attive in quel momento;
  • Hash - Una funzione di hashing è utilizzata come funzione di lookup per assegnare univocamente un server ad un determinato client. La variabile da utilizzare come chiave di hashing viene impostata nella configurazione;
  • Random - Seleziona il server di upstream in modo casuale;

Il metodo round-robin è quello attivo per default e pertanto non è associato ad alcuna direttiva. Ogni blocco upstream funziona in modalità round-robin a meno che un'altra modalità non sia esplicitamente indicata.

La modalità hash viene utilizzata per implementare la persistenza delle sessioni. L'obiettivo è quello di evitare che i dati provenienti da un client possano essere gestiti da più server di upstream. Poiché il concetto di sessione così come le modalità con le quali essa viene gestita dipendono essenzialmente dal protocollo applicativo in uso, Nginx non può fare alcuna supposizione in merito. Pertanto, viene lasciata facoltà di definire un criterio opportuno specificando una chiave per la funzione di hashing da utilizzare. Ad esempio, per utilizzare come chiave di hashing l'indirizzo IP del client, si può specificare:

stream {
    upstream dns_servers {
        hash $remote_addr;
        server server1.example.com:123;
        server server2.example.com:123;
        server server3.example.com:123;
    }
}

è possibile inoltre attivare il consistent hashing aggiungendo alla direttiva hash il parametro consistent. Così facendo Nginx utilizzerà le funzioni di hashing implementate nella libreria ketama. A differenza delle funzioni di hashing lineare, il consistent hashing permette di ridurre al minimo il numero di valori di hash che cambieranno a parità di chiave nel caso in cui la dimensione della tabella di hashing dovesse variare. Nel caso specifico, la funzione di hashing è utilizzata per individuare il server di upstream da utilizzare. Essa pertanto produrrà un valore numerico compreso tra 0 ed il numero di server in upstream. In altre parole, se i server di upstream sono tre, come nell'esempio, i possibili valori di output della funzione di hashing sono 0, 1 e 2. Supponendo di aggiungere un quarto server di upstream, i valori di output diventano 0, 1, 2 e 3. Nel caso dell'hashing lineare, a parità di chiavi in input tutti i valori in output cambiano. Ciò può comportare delle inconsistenze nel caso in cui si modifichi frequentemente la lista di server in upstream. Con il consistent hashing il problema non si verifica.

Specifica dei pesi

Come nel caso del load balancing HTTP, è inoltre possibile assegnare dei pesi specifici ai singoli server in upstream, mediante il parametro weight. Si può inoltre specificare un limite sul numero massimo di connessioni che un server di upstream può gestire, con il parametro max_conns. Ad esempio:

upstream stream_backend {
    hash   $remote_addr consistent;
    server backend1.example.com:12345 weight=5;
    server backend2.example.com:12345;
    server backend3.example.com:12346 max_conns=3;
}
upstream dns_servers {
    least_conn;
    server 192.168.136.130:53;
    server 192.168.136.131:53;
    # ...
}

Con questa configurazione verrà scelto il server con meno connessioni attive. Tuttavià, se il server scelto è il server backend3 esso verrà selezionato solo se ha meno di tre connessioni in corso. Inoltre, nel caso in cui vi siano più sever che rispondano al criterio di selezione (ad esempio, due server con nessuna connessione in corso), essi verranno selezionati tenendo conto del peso specificato nel parametro weight.

Ti consigliamo anche