Linee guida per i test di carico dei servizi di backend con i bilanciatori del carico delle applicazioni

Durante l'integrazione di un servizio di backend con il bilanciatore del carico delle applicazioni, è importante misurare le prestazioni di un servizio di backend da solo, in assenza di un bilanciatore del carico. I test di carico in condizioni controllate ti aiutano a valutare compromessi nella pianificazione della capacità tra le diverse dimensioni delle prestazioni, come velocità effettiva e latenza. Poiché un'attenta pianificazione della capacità potrebbe sottostimare la domanda effettiva, ti consigliamo di usare i test di carico per determinare come viene influenzata la disponibilità di un servizio quando il sistema sovraccarico.

Obiettivi dei test di carico

Un tipico test di carico misura il comportamento visibile all'esterno del backend con diverse dimensioni di carico. Di seguito sono riportate alcune delle dimensioni più pertinenti di questi test:

  • Throughput delle richieste: il numero di richieste gestite al secondo.
  • Contemporaneità delle richieste: il numero di richieste elaborate contemporaneamente.
  • Velocità effettiva connessione: il numero di connessioni avviate dai client e un numero elevato di operazioni di I/O al secondo. La maggior parte dei servizi che utilizzano Transport Layer Security (TLS) offre il trasporto di rete e l'overhead di negoziazione TLS associato a ogni indipendente dall'elaborazione delle richieste.
  • Contemporaneità delle connessioni: il numero di connessioni client elaborate contemporaneamente.

  • Latenza della richiesta: il tempo totale trascorso tra l'inizio della richiesta e la fine della risposta.

  • Tasso di errori: la frequenza con cui le richieste causano errori, ad esempio errori HTTP 5xx e chiusure premature delle connessioni.

Per valutare l'integrità del server sotto carico, potrebbe essere utilizzata anche una procedura di test di carico raccolgono le seguenti metriche dei servizi interni:

  • Utilizzo delle risorse di sistema: le risorse di sistema, come CPU, RAM e handle file (socket), sono in genere espresse in percentuale.

    L'importanza di queste metriche varia in base a come viene implementato il servizio. Le applicazioni registrano prestazioni ridotte, calo del carico un arresto anomalo quando esauriscono le risorse. Pertanto, diventa essenziale determinare la disponibilità delle risorse quando un host è sotto carico elevato.

  • Utilizzo di altre risorse limitate: risorse non di sistema che potrebbero essere esauriti sotto carico, ad esempio a livello di applicazione.

    Alcuni esempi di risorse di questo tipo includono:

    • Un pool limitato di thread o processi worker.
    • Per un server applicazioni che utilizza i thread, è comune limitare il numero di thread di lavoro in esecuzione contemporaneamente. I limiti delle dimensioni del pool di thread sono utili per evitare l'esaurimento della memoria e della CPU, ma spesso le impostazioni predefinite sono molto conservativo. Limiti troppo bassi potrebbero impedire un utilizzo adeguato delle risorse di sistema.
    • Alcuni server utilizzano pool di processi anziché pool di thread. Ad esempio, un Server Apache quando viene configurato con il metodo Prefork Multi-Processing modello, assegna un processo a ogni connessione del client. Quindi, il limite di dimensione determina il limite superiore di contemporaneità delle connessioni.
    • Un servizio di cui è stato eseguito il deployment come frontend di un altro servizio che ha un pool di connessioni di backend di dimensioni limitate.

Pianificazione della capacità rispetto ai test di sovraccarico

Gli strumenti di test di carico ti aiutano a misurare singolarmente le diverse dimensioni di scalabilità. Per la pianificazione della capacità, determina la soglia di carico per il il rendimento in più dimensioni. Ad esempio, invece di misurare assoluto di una richiesta di servizio, ti consigliamo di misurare seguenti:

  • La frequenza di richiesta con cui il servizio può essere pubblicato con una latenza del 99° percentile inferiore a un numero specificato di millisecondi. Il numero è specificato dallo SLO del servizio.
  • La frequenza massima di richieste che non provoca il superamento dell'utilizzo delle risorse di sistema livelli ottimali. Tieni presente che l'utilizzo ottimale varia in base all'applicazione e potrebbe essere significativamente inferiore al 100%. Ad esempio, con un picco di utilizzo della memoria all'80%, l'applicazione potrebbe essere in grado di gestire picchi di carico minori meglio che se l'utilizzo di picco fosse al 99%.

Sebbene sia importante utilizzare i risultati dei test di carico per prendere decisioni relative alla pianificazione della capacità, è altrettanto importante comprendere il comportamento di un servizio quando il carico supera la capacità. Alcuni comportamenti del server che vengono spesso valutati mediante il sovraccarico. sono i seguenti:

  • Ridondanza: quando un servizio riceve richieste o connessioni in entrata eccessive, potrebbe rispondere rallentando tutte le richieste o rifiutandone alcune per mantenere un rendimento accettabile per le rimanenti. Me consigliamo il secondo approccio per evitare i timeout del client prima di ricevere e per ridurre il rischio di esaurimento della memoria riducendo la richiesta e contemporaneità sul server.

  • Resilienza all'esaurimento delle risorse: in genere un servizio evita di bloccarsi per esaurimento delle risorse perché è difficile per le richieste in attesa fare ulteriori progressi se il servizio si è bloccato. Se un servizio di backend ha in molti casi, la robustezza delle singole istanze è fondamentale per la la disponibilità del servizio. Mentre un'istanza si riavvia in seguito a un arresto anomalo, le istanze potrebbero subire un carico maggiore, causando potenzialmente un errore a cascata.

Linee guida generali per i test

Quando definisci i casi di test, tieni presenti le seguenti linee guida.

Crea test su scala ridotta

Crea test su scala ridotta per misurare i limiti delle prestazioni del server. Con del server, c'è il rischio che un test non riveli limiti delle prestazioni del servizio stesso, ma potrebbero individuare colli di bottiglia in altre sistemi diversi, come gli host del client o il livello di rete.

Per ottenere risultati ottimali, prendi in considerazione uno scenario di test che utilizza una singola macchina virtuale (VM) o un pod di Google Kubernetes Engine (GKE) per testare il servizio in modo indipendente. Per ottenere il carico completo sul server, se necessario, puoi utilizzare più VM, ma ricorda che possono complicare la raccolta dei dati sulle prestazioni.

Scegliere i pattern di carico a ciclo aperto

La maggior parte dei generatori di carico utilizza il pattern a circuito chiuso per limitare il numero di richieste in parallelo e ritardare le nuove richieste fino al completamento di quelle precedenti. Sconsigliamo questo approccio perché i client di produzione del servizio potrebbero non mostrare questo comportamento di throttling.

Al contrario, il pattern a ciclo aperto consente ai generatori di carico di simulare il carico di produzione inviando richieste a una frequenza costante, indipendentemente dalla frequenza con cui arrivano le risposte del server.

Consigliamo i seguenti generatori di carico per il test di carico del backend servizio:

Nighthawk

Nighthawk è uno strumento open source sviluppato in collaborazione con il progetto Envoy. Puoi usarlo per generare il carico del client, visualizzare i benchmark e misurare le prestazioni del server per la maggior parte degli scenari di test di carico dei servizi HTTPS.

Test HTTP/1

Per testare HTTP/1, utilizza il seguente comando:

nighthawk_client URI \
    --duration DURATION \
    --open-loop \
    --no-default-failure-predicates \
    --protocol http1 \
    --request-body-size REQ_BODY_SIZE \
    --concurrency CONCURRENCY \
    --rps RPS \
    --connections CONNECTIONS

Sostituisci quanto segue:

  • URI: l'URI da sottoporre a benchmark
  • DURATION: tempo di esecuzione totale del test in secondi
  • REQ_BODY_SIZE: dimensione del payload POST in ogni richiesta
  • CONCURRENCY: il numero totale di eventi simultanei loop

    Questo numero deve corrispondere al conteggio dei core della VM client

  • RPS: frequenza target di richieste al secondo per loop di eventi

  • CONNECTIONS: il numero di connessioni simultanee per loop di eventi

Vedi l'esempio che segue:

nighthawk_client http://10.20.30.40:80 \
    --duration 600 --open-loop --no-default-failure-predicates \
    --protocol http1 --request-body-size 5000 \
    --concurrency 16 --rps 500 --connections 200

L'output di ogni esecuzione di test fornisce un istogramma delle latenze di risposta. Nella esempio del canale Nighthawk documentazione , noterai che la latenza al 99° percentile è di circa 135 microsecondi.

Initiation to completion
    samples: 9992
    mean:    0s 000ms 113us
    pstdev:  0s 000ms 061us

    Percentile  Count       Latency
    0           1           0s 000ms 077us
    0.5         4996        0s 000ms 115us
    0.75        7495        0s 000ms 118us
    0.8         7998        0s 000ms 118us
    0.9         8993        0s 000ms 121us
    0.95        9493        0s 000ms 124us
    0.990625    9899        0s 000ms 135us
    0.999023    9983        0s 000ms 588us
    1           9992        0s 004ms 090us

Testa HTTP/2

Per testare HTTP/2, utilizza il seguente comando:

nighthawk_client URI \
    --duration DURATION \
    --open-loop \
    --no-default-failure-predicates \
    --protocol http2 \
    --request-body-size REQ_BODY_SIZE \
    --concurrency CONCURRENCY \
    --rps RPS \
    --max-active-requests MAX_ACTIVE_REQUESTS \
    --max-concurrent-streams MAX_CONCURRENT_STREAMS

Sostituisci quanto segue:

  • URI: l'URI da sottoporre a benchmark
  • DURATION: tempo di esecuzione totale del test in secondi
  • REQ_BODY_SIZE: dimensione del payload POST in ogni richiesta
  • CONCURRENCY: il numero totale di eventi simultanei loop

    Questo numero deve corrispondere al conteggio dei core della VM client

  • RPS: la frequenza target di richieste al secondo per ogni loop di eventi

  • MAX_ACTIVE_REQUESTS: il numero massimo di richieste attive simultanee per ogni loop di eventi

  • MAX_CONCURRENT_STREAMS: il numero massimo di Stream simultanei consentiti su ogni connessione HTTP/2

Vedi il seguente esempio:

nighthawk_client http://10.20.30.40:80 \
    --duration 600 --open-loop --no-default-failure-predicates \
    --protocol http2 --request-body-size 5000 \
    --concurrency 16 --rps 500 \
    --max-active-requests 200 --max-concurrent-streams 1

ab (strumento di benchmark Apache)

ab è un'alternativa meno flessibile a Nighthawk, ma è disponibile come pacchetto su in quasi tutte le distribuzioni Linux. ab è consigliato solo per test rapidi e semplici.

Per installare ab, utilizza il seguente comando:

  • Su Debian e Ubuntu, esegui sudo apt-get install apache2-utils.
  • Nelle distribuzioni basate su RedHat, esegui sudo yum install httpd-utils.

Dopo aver installato ab, utilizza il seguente comando per eseguirlo:

ab -c CONCURRENCY \
    -n NUM_REQUESTS \
    -t TIMELIMIT \
    -p POST_FILE URI

Sostituisci quanto segue:

  • CONCURRENCY: numero di richieste in parallelo a eseguire
  • NUM_REQUESTS: numero di richieste da eseguire
  • TIMELIMIT: numero massimo di secondi da dedicare alle richieste
  • POST_FILE: file locale contenente il payload del POST HTTP
  • URI: l'URI da sottoporre a benchmark

Vedi l'esempio che segue:

ab -c 200 -n 1000000 -t 600 -P body http://10.20.30.40:80

Il comando nell'esempio precedente invia richieste con una contemporaneità di 200 (pattern a circuito chiuso) e si arresta dopo 1.000.000 (un milione) di richieste o 600 secondi di tempo trascorso. Il comando include anche i contenuti il file body come payload POST HTTP.

Il comando ab produce istogrammi per la latenza di risposta simili a quelli Nighthawk, ma la sua risoluzione è limitata ai millisecondi, anziché microsecondi:

Percentage of the requests served within a certain time (ms)
    50%     7
    66%     7
    75%     7
    80%     7
    90%    92
    95%   121
    98%   123
    99%   127
    100%  156 (longest request)

Passaggi successivi