Ottimizza la scalabilità automatica del servizio Amazon ECS - Amazon Elastic Container Service

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Ottimizza la scalabilità automatica del servizio Amazon ECS

Un servizio Amazon ECS è una raccolta gestita di attività. Ogni servizio ha una definizione di attività associata, un numero di attività desiderato e una strategia di posizionamento opzionale. La scalabilità automatica del servizio Amazon ECS viene implementata tramite il servizio Application Auto Scaling. Application Auto Scaling utilizza le CloudWatch metriche come fonte per le metriche di scalabilità. Utilizza inoltre gli CloudWatch allarmi per impostare soglie su quando ampliare o disattivare il servizio. Puoi fornire le soglie per la scalabilità impostando un obiettivo metrico, denominato ridimensionamento del tracciamento degli obiettivi, o specificando delle soglie, denominate scalabilità dei passaggi. Una volta configurato, Application Auto Scaling calcola continuamente il numero di attività desiderato appropriato per il servizio. Inoltre, notifica ad Amazon ECS quando il numero di attività desiderato deve cambiare, ridimensionandolo orizzontalmente o ridimensionandolo.

Per utilizzare il service auto scaling in modo efficace, è necessario scegliere una metrica di scalabilità appropriata.

Un'applicazione deve essere scalata orizzontalmente se si prevede che la domanda sia superiore alla capacità attuale. Al contrario, un'applicazione può essere scalata per ridurre i costi quando le risorse superano la domanda.

Identifica una metrica

Per una scalabilità efficace, è fondamentale identificare una metrica che indichi l'utilizzo o la saturazione. Questa metrica deve presentare le seguenti proprietà per essere utile per la scalabilità.

  • La metrica deve essere correlata alla domanda. Quando le risorse vengono mantenute stabili, ma la domanda cambia, anche il valore della metrica deve cambiare. La metrica dovrebbe aumentare o diminuire quando la domanda aumenta o diminuisce.

  • Il valore della metrica deve essere scalato in proporzione alla capacità. Quando la domanda rimane costante, l'aggiunta di più risorse deve comportare una modifica proporzionale del valore della metrica. Pertanto, il raddoppio del numero di attività dovrebbe far diminuire la metrica del 50%.

Il modo migliore per identificare una metrica di utilizzo è eseguire test di carico in un ambiente di preproduzione come un ambiente di staging. Le soluzioni commerciali e open source per i test di carico sono ampiamente disponibili. Queste soluzioni in genere possono generare carichi sintetici o simulare il traffico utente reale.

Per avviare il processo di test di carico, crea dashboard per le metriche di utilizzo dell'applicazione. Queste metriche includono l'utilizzo della CPU, l'utilizzo della memoria, la profondità della I/O operations, I/O coda e il throughput di rete. Puoi raccogliere queste metriche con un servizio come Container Insights. Per ulteriori informazioni, consulta Monitora i contenitori Amazon ECS utilizzando Container Insights con osservabilità migliorata. Durante questo processo, assicurati di raccogliere e tracciare le metriche relative ai tempi di risposta dell'applicazione o ai tassi di completamento del lavoro.

Inizia con una piccola richiesta o una percentuale di inserimento lavorativo ridotta. Mantieni questa frequenza costante per diversi minuti per consentire all'applicazione di riscaldarsi. Quindi, aumenta lentamente la velocità e mantienila costante per alcuni minuti. Ripeti questo ciclo, aumentando ogni volta la frequenza fino a quando i tempi di risposta o di completamento dell'applicazione non saranno troppo lenti per soddisfare gli obiettivi in termini di livello di servizio (). SLOs

Durante il test di carico, esaminate ciascuna metrica di utilizzo. Le metriche che aumentano insieme al carico sono le migliori candidate a fungere da migliori metriche di utilizzo.

Successivamente, identifica la risorsa che raggiunge la saturazione. Allo stesso tempo, esamina anche le metriche di utilizzo per vedere quale si appiattisce prima ad un livello elevato o raggiunge un picco e poi blocca prima l'applicazione. Ad esempio, se l'utilizzo della CPU aumenta dallo 0% al 70-80% man mano che si aggiunge carico e poi rimane a quel livello dopo aver aggiunto ancora più carico, si può affermare con certezza che la CPU è satura. A seconda dell'architettura della CPU, potrebbe non raggiungere mai il 100%. Ad esempio, supponiamo che l'utilizzo della memoria aumenti man mano che aggiungi carico e che l'applicazione si blocchi improvvisamente quando raggiunge il limite di memoria dell'attività o dell' EC2 istanza Amazon. In questa situazione, è probabile che la memoria sia stata completamente consumata. L'applicazione potrebbe consumare più risorse. Pertanto, scegli la metrica che rappresenta la risorsa che si esaurisce per prima.

Infine, riprova a testare il carico dopo aver raddoppiato il numero di attività o EC2 istanze Amazon. Supponiamo che la metrica chiave aumenti o diminuisca della metà rispetto a prima. In tal caso, la metrica è proporzionale alla capacità. Questa è una buona metrica di utilizzo per la scalabilità automatica.

Consideriamo ora questo scenario ipotetico. Supponiamo di testare un'applicazione e di scoprire che l'utilizzo della CPU alla fine raggiunge l'80% a 100 richieste al secondo. Quando viene aggiunto più carico, non aumenta più l'utilizzo della CPU. Tuttavia, fa sì che l'applicazione risponda più lentamente. Quindi, si esegue nuovamente il test di carico, raddoppiando il numero di attività ma mantenendo la frequenza al valore di picco precedente. Se ritieni che l'utilizzo medio della CPU scenda a circa il 40%, l'utilizzo medio della CPU è un buon candidato per una metrica di scalabilità. D'altra parte, se l'utilizzo della CPU rimane all'80% dopo l'aumento del numero di attività, l'utilizzo medio della CPU non è una buona metrica di scalabilità. In tal caso, sono necessarie ulteriori ricerche per trovare una metrica adeguata.

Modelli applicativi e proprietà di scalabilità comuni

Vengono eseguiti software di tutti i tipi. AWS Molti carichi di lavoro sono creati internamente, mentre altri si basano su popolari software open source. Indipendentemente dalla loro origine, abbiamo osservato alcuni modelli di progettazione comuni per i servizi. La scalabilità efficace dipende in gran parte dal modello.

L'efficiente server legato alla CPU

L'efficiente server legato alla CPU non utilizza quasi nessuna risorsa oltre alla CPU e al throughput di rete. Ogni richiesta può essere gestita dalla sola applicazione. Le richieste non dipendono da altri servizi come i database. L'applicazione è in grado di gestire centinaia di migliaia di richieste simultanee e a tale scopo può utilizzarne più CPUs di una in modo efficiente. Ogni richiesta è gestita da un thread dedicato con un basso sovraccarico di memoria oppure esiste un ciclo di eventi asincrono che viene eseguito su ogni CPU che soddisfa le richieste. Ogni replica dell'applicazione è ugualmente in grado di gestire una richiesta. L'unica risorsa che potrebbe esaurirsi prima della CPU è la larghezza di banda della rete. Nei servizi legati alla CPU, l'utilizzo della memoria, anche al picco della velocità effettiva, è una frazione delle risorse disponibili.

Questo tipo di applicazione è adatto per il ridimensionamento automatico basato su CPU. L'applicazione gode della massima flessibilità in termini di scalabilità. Può essere scalato verticalmente fornendo EC2 istanze Amazon più grandi o Fargate v. CPUs Inoltre, può essere ridimensionato orizzontalmente aggiungendo altre repliche. L'aggiunta di più repliche o il raddoppio delle dimensioni dell'istanza dimezzano l'utilizzo medio della CPU rispetto alla capacità.

Se utilizzi la EC2 capacità di Amazon per questa applicazione, valuta la possibilità di collocarla su istanze ottimizzate per il calcolo come la c5 famiglia or. c6g

L'efficiente server legato alla memoria

L'efficiente server legato alla memoria alloca una quantità significativa di memoria per richiesta. In caso di massima concorrenza, ma non necessariamente della velocità effettiva, la memoria si esaurisce prima dell'esaurimento delle risorse della CPU. La memoria associata a una richiesta viene liberata al termine della richiesta. Le richieste aggiuntive possono essere accettate purché sia disponibile memoria.

Questo tipo di applicazione è adatto per il ridimensionamento automatico basato sulla memoria. L'applicazione gode della massima flessibilità in termini di scalabilità. Può essere scalato sia verticalmente fornendogli risorse di memoria Amazon o EC2 Fargate più grandi. Inoltre, può essere ridimensionato orizzontalmente aggiungendo altre repliche. L'aggiunta di più repliche o il raddoppio delle dimensioni dell'istanza possono dimezzare l'utilizzo medio della memoria rispetto alla capacità.

Se utilizzi la EC2 capacità di Amazon per questa applicazione, valuta la possibilità di collocarla su istanze ottimizzate per la memoria come la r5 famiglia or. r6g

Alcune applicazioni legate alla memoria non liberano la memoria associata a una richiesta al termine, quindi una riduzione della concorrenza non si traduce in una riduzione della memoria utilizzata. Per questo, non è consigliabile utilizzare il ridimensionamento basato sulla memoria.

Il server basato sul lavoratore

Il server basato sul lavoratore elabora una richiesta per ogni singolo thread di lavoro una dopo l'altra. I thread di lavoro possono essere thread leggeri, come thread POSIX. Possono anche essere thread più pesanti, come i processi UNIX. Indipendentemente dal thread, c'è sempre una concorrenza massima che l'applicazione è in grado di supportare. Di solito il limite di concorrenza è impostato proporzionalmente alle risorse di memoria disponibili. Se viene raggiunto il limite di concorrenza, le richieste aggiuntive vengono inserite in una coda di backlog. Se la coda del backlog supera i limiti, le richieste aggiuntive in arrivo vengono immediatamente respinte. Le applicazioni più comuni che si adattano a questo modello includono il server web Apache e Gunicorn.

La concorrenza delle richieste è in genere la metrica migliore per scalare questa applicazione. Poiché esiste un limite di concorrenza per ogni replica, è importante eseguire la scalabilità orizzontale prima che venga raggiunto il limite medio.

Il modo migliore per ottenere le metriche relative alla concorrenza delle richieste consiste nel farle riportare dall'applicazione. CloudWatch Ogni replica dell'applicazione può pubblicare il numero di richieste simultanee come metrica personalizzata ad alta frequenza. Si consiglia di impostare la frequenza su almeno una volta al minuto. Dopo aver raccolto diversi report, puoi utilizzare la concorrenza media come metrica di scala. Questa metrica viene calcolata prendendo la concorrenza totale e dividendola per il numero di repliche. Ad esempio, se la concorrenza totale è 1000 e il numero di repliche è 10, la concorrenza media è 100.

Se la tua applicazione è alla base di un Application Load Balancer, puoi anche utilizzare la ActiveConnectionCount metrica per il load balancer come fattore nella metrica di scalabilità. La ActiveConnectionCount metrica deve essere divisa per il numero di repliche per ottenere un valore medio. Per la scalatura deve essere utilizzato il valore medio, anziché il valore di conteggio non elaborato.

Affinché questa progettazione funzioni al meglio, la deviazione standard della latenza di risposta deve essere piccola a basse frequenze di richiesta. Consigliamo che, durante i periodi di scarsa domanda, la maggior parte delle richieste riceva risposta in breve tempo e che non molte richieste impieghino molto più tempo della media per rispondere. Il tempo di risposta medio dovrebbe essere vicino al tempo di risposta del 95° percentile. In caso contrario, potrebbero verificarsi sovraccarichi dalla coda. Ciò porta a errori. Si consiglia di fornire repliche aggiuntive laddove necessario per mitigare il rischio di overflow.

Il server di attesa

Il server di attesa esegue alcune elaborazioni per ogni richiesta, ma il funzionamento dipende in larga misura da uno o più servizi a valle. Le applicazioni container spesso fanno un uso intensivo di servizi downstream come database e altri servizi API. La risposta di questi servizi può richiedere del tempo, in particolare in scenari ad alta capacità o ad alta concorrenza. Questo perché queste applicazioni tendono a utilizzare poche risorse della CPU e a sfruttare la massima concorrenza in termini di memoria disponibile.

Il servizio di attesa è adatto sia nel modello di server legato alla memoria che nel modello di server basato sui lavoratori, a seconda di come è progettata l'applicazione. Se la concorrenza dell'applicazione è limitata solo dalla memoria, l'utilizzo medio della memoria deve essere utilizzato come metrica di scalabilità. Se la concorrenza dell'applicazione si basa su un limite di lavoratori, è necessario utilizzare la concorrenza media come metrica di scalabilità.

Il server basato su Java

Se il server basato su Java è legato alla CPU e si adatta proporzionalmente alle risorse della CPU, potrebbe essere adatto all'efficiente modello di server associato alla CPU. In tal caso, l'utilizzo medio della CPU potrebbe essere appropriato come metrica di scalabilità. Tuttavia, molte applicazioni Java non sono legate alla CPU, il che le rende difficili da scalare.

Per prestazioni ottimali, si consiglia di allocare quanta più memoria possibile all'heap Java Virtual Machine (JVM). Le versioni recenti di JVM, tra cui Java 8 update 191 o versioni successive, impostano automaticamente la dimensione dell'heap il più grande possibile per adattarla al contenitore. Ciò significa che, in Java, l'utilizzo della memoria è raramente proporzionale all'utilizzo delle applicazioni. Con l'aumento della frequenza delle richieste e della concorrenza, l'utilizzo della memoria rimane costante. Per questo motivo, non è consigliabile scalare i server basati su Java in base all'utilizzo della memoria. Al contrario, in genere consigliamo di ridimensionare l'utilizzo della CPU.

In alcuni casi, i server basati su Java incontrano l'esaurimento dell'heap prima di esaurire la CPU. Se l'applicazione è soggetta all'esaurimento dell'heap in caso di elevata simultaneità, la metrica di scalabilità migliore è rappresentata dalle connessioni medie. Se la tua applicazione è soggetta all'esaurimento dell'heap a un throughput elevato, la frequenza media delle richieste è la metrica di scalabilità migliore.

Server che utilizzano altri runtime raccolti tramite garbage

Molte applicazioni server si basano su runtime che eseguono la raccolta dei dati indesiderati, ad esempio .NET e Ruby. Queste applicazioni server potrebbero rientrare in uno dei modelli descritti in precedenza. Tuttavia, come nel caso di Java, non è consigliabile scalare queste applicazioni in base alla memoria, poiché il loro utilizzo medio della memoria osservato spesso non è correlato alla velocità effettiva o alla concorrenza.

Per queste applicazioni, si consiglia di ridimensionare l'utilizzo della CPU se l'applicazione è vincolata alla CPU. Altrimenti, consigliamo di scalare in base al throughput medio o alla concorrenza media, in base ai risultati dei test di carico.

Job processor

Molti carichi di lavoro prevedono l'elaborazione asincrona dei processi. Includono applicazioni che non ricevono richieste in tempo reale, ma si iscrivono a una coda di lavoro per ricevere offerte di lavoro. Per questi tipi di applicazioni, la metrica di scalabilità corretta è quasi sempre la profondità della coda. L'aumento della coda indica che il lavoro in sospeso supera la capacità di elaborazione, mentre una coda vuota indica che c'è più capacità del lavoro da fare.

AWS i servizi di messaggistica, come Amazon SQS e Amazon Kinesis Data Streams, CloudWatch forniscono metriche che possono essere utilizzate per la scalabilità. Per Amazon SQS, ApproximateNumberOfMessagesVisible è la metrica migliore. Per Kinesis Data Streams, prendi in considerazione l'MillisBehindLatestutilizzo della metrica, pubblicata dalla Kinesis Client Library (KCL). È necessario calcolare la media di questa metrica tra tutti i consumatori prima di utilizzarla per la scalabilità.