2009-08-17 3 views
21

Come si determina il numero migliore di maxSpare, minSpire e maxThreads, acceptCount ecc in Tomcat? Le migliori pratiche esistenti sono?Come determinare il miglior numero di thread in Tomcat?

Capisco che questo deve essere basato sull'hardware (ad es. Per core) e può essere solo una base per ulteriori test di performance e ottimizzazione su hardware specifico.

risposta

46

il problema "quanti thread" è un problema piuttosto complesso e complesso e non è possibile rispondere con una semplice regola empirica.

Considerando il numero di core disponibili è utile per le applicazioni multi-thread che tendono a consumare molta CPU, come il numero di crunch e simili. Questo è raramente il caso di un'applicazione web, che di solito è impedita dalla CPU ma da altri fattori.

Una limitazione comune è il ritardo tra l'utente e altri sistemi esterni, in particolare il DB. Ogni volta che arriva una richiesta, probabilmente interrogherà il database un certo numero di volte, il che significa che lo streaming di alcuni byte su una connessione JDBC, quindi in attesa che quei byte arrivino al database (anche se è su localhost c'è ancora un piccolo ritardo) , quindi aspettiamo che il DB consideri la nostra richiesta, quindi attendi che il database lo elabori (il database stesso attenderà che il disco cerchi una determinata regione) ecc ...

Durante tutto questo tempo, il thread è inattivo, quindi un altro thread potrebbe facilmente utilizzare le risorse della CPU per fare qualcosa di utile. È abbastanza comune vedere dal 40% all'80% del tempo speso ad aspettare la risposta del DB.

Lo stesso accade anche sull'altro lato della connessione. Mentre un tuo thread sta scrivendo il suo output sul browser, la velocità della connessione CLIENT può mantenere il tuo thread inattivo aspettando che il browser accetti che un certo pacchetto sia stato ricevuto. (Questo era un problema un bel po 'di anni fa, i kernel recenti e le JVM usano buffer più grandi per evitare che i thread venissero inattivi in ​​quel modo, tuttavia un proxy inverso di fronte al tuo server di applicazioni web, anche semplicemente un httpd, può essere davvero utile per evitare le persone con una cattiva connessione internet per agire come attacchi DDOS :))

Considerando questi fattori, il numero di thread dovrebbe essere in genere molto più dei core che hai. Anche su un semplice server dual o quad core, dovresti configurare almeno qualche dozzina di thread.

Quindi, qual è il limite del numero di thread che è possibile configurare?

Prima di tutto, ogni thread (utilizzato per) consuma molte risorse. Ogni thread ha uno stack, che consuma RAM. Inoltre, ogni Thread allocherà effettivamente le cose sull'heap per fare il suo lavoro, consumando di nuovo la RAM, e l'atto di passare da un thread all'altro (cambio di contesto) è piuttosto pesante per il kernel JVM/OS.

Ciò rende difficile eseguire un server con migliaia di thread "senza problemi".

Dato questo quadro, ci sono una serie di tecniche (per lo più: provare, fallire, sintonia, provare di nuovo) per determinare più o meno il numero di thread si app necessario:

1) cercare di capire dove il vostro i thread trascorrono del tempo. Esistono numerosi buoni strumenti, ma anche il profiler di jvisualvm può essere un ottimo strumento o un aspetto di tracciatura che produce statistiche di temporizzazione sommarie. Più tempo passano in attesa di qualcosa di esterno, più è possibile generare più thread per utilizzare la CPU durante i periodi di inattività.

2) Determinare l'utilizzo della RAM.Dato che la JVM utilizzerà una certa quantità di memoria (in particolare lo spazio permgen, in genere fino a 100 megabyte, ancora una volta jvisualvm lo dirà) indipendentemente dal numero di thread che usi, prova a eseguire con un thread e poi con dieci e poi con cento, pur sottolineando l'app con jmeter o qualsiasi altra cosa, e vediamo come crescerà l'utilizzo dell'heap. Questo può rappresentare un limite difficile.

3) Provare a determinare un obiettivo. Ogni richiesta utente ha bisogno di una discussione da gestire. Se il tempo di risposta medio è 200ms per "get" (sarebbe meglio non considerare il caricamento di immagini, CSS e altre risorse statiche), quindi ogni thread è in grado di servire 4/5 pagine al secondo. Se ogni utente dovrebbe "cliccare" ogni 3/4 secondi (dipende, è un browser game o un sito con molti testi lunghi?), Quindi un thread "servirà 20 utenti simultanei", qualunque cosa significhi. Se nell'ora di punta hai 500 utenti singoli che colpiscono il tuo sito in 1 minuto, allora hai bisogno di thread sufficienti per gestirlo.

4) Verificare il limite superiore. Usa jmeter, configura un server con molti thread su una macchina virtuale di riserva e osserva come i tempi di risposta peggiorano quando superi un certo limite. Più dell'hardware, l'implementazione del thread del sistema operativo sottostante è importante qui, ma non importa cosa colpirà un punto in cui la CPU impiegherà più tempo a cercare di capire quale thread eseguire piuttosto che eseguirlo, e quel numero non è così incredibilmente alta.

5) Considerare in che modo le discussioni influenzeranno altri componenti. Ogni thread probabilmente utilizzerà una (o forse più di una) connessione al database, il database è in grado di gestire connessioni simultanee 50/100/500? Anche se si utilizza un cluster semplificato di server nosql, la server farm offre una larghezza di banda sufficiente tra quelle macchine? Cos'altro può essere eseguito sulla stessa macchina con il server di app Web? Anache httpd? calamaro? il database stesso? un proxy di caching locale per il database come mongos o memcached?

Ho visto sistemi in produzione con solo 4 thread + 4 thread di riserva, perché il lavoro svolto da quel server era semplicemente quello di ridimensionare le immagini, quindi era quasi il 100% di utilizzo della CPU, e altri configurati più o meno il stesso hardware con un paio di centinaia di thread, perché la webapp stava facendo molte chiamate SOAP a sistemi esterni e trascorreva la maggior parte del tempo in attesa di risposte.

Oce hai determinato il ca. thread minimi e massimi ottimali per la tua webapp, quindi di solito la configuro in questo modo:

1) Sulla base dei vincoli sulla RAM, altre risorse esterne ed esperimenti sul cambio di contesto, c'è un massimo assoluto che non deve essere raggiunto. Quindi, usa maxThreads per limitarlo a circa la metà o il 3/4 di quel numero.

2) Se l'applicazione è ragionevolmente veloce (ad esempio, espone REST servizi web che di solito inviare una risposta è a pochi millesimi di secondo), quindi è possibile configurare un grande acceptCount, fino allo stesso numero di maxThreads. Se si dispone di un servizio di bilanciamento del carico di fronte al server delle applicazioni Web, impostare un acceptCount di piccole dimensioni, è preferibile che il servizio di bilanciamento del carico visualizzi le richieste non accettate e passi a un altro server anziché mettere gli utenti in attesa su uno già occupato.

3) Poiché l'avvio di un thread è (ancora) considerato un'operazione pesante, utilizzare minSpareThreads per avere alcuni thread pronti all'arrivo delle ore di punta. Questo dipende ancora dal tipo di carico che ci si aspetta. È anche ragionevole avere l'impostazione di minSpareThreads, maxSpareThreads e maxThreads in modo che un numero esatto di thread sia sempre pronto, mai reclamato e le prestazioni sono prevedibili. Se si esegue tomcat su un computer dedicato, è possibile generare minSpareThreads e maxSpareThreads senza il pericolo di eseguire il log degli altri processi, altrimenti ridurli in modo che i thread siano risorse condivise con il resto dei processi in esecuzione sulla maggior parte del sistema operativo.