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.
Esegui test utilizzando generatori di carico consigliati
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 benchmarkDURATION
: tempo di esecuzione totale del test in secondiREQ_BODY_SIZE
: dimensione del payload POST in ogni richiestaCONCURRENCY
: il numero totale di eventi simultanei loopQuesto numero deve corrispondere al conteggio dei core della VM client
RPS
: frequenza target di richieste al secondo per loop di eventiCONNECTIONS
: 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 benchmarkDURATION
: tempo di esecuzione totale del test in secondiREQ_BODY_SIZE
: dimensione del payload POST in ogni richiestaCONCURRENCY
: il numero totale di eventi simultanei loopQuesto numero deve corrispondere al conteggio dei core della VM client
RPS
: la frequenza target di richieste al secondo per ogni loop di eventiMAX_ACTIVE_REQUESTS
: il numero massimo di richieste attive simultanee per ogni loop di eventiMAX_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 eseguireNUM_REQUESTS
: numero di richieste da eseguireTIMELIMIT
: numero massimo di secondi da dedicare alle richiestePOST_FILE
: file locale contenente il payload del POST HTTPURI
: 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)