Quanti thread devo usare nel mio server NIO?

5

Ho creato un server TCP NIO Java, attualmente utilizza quattro thread. Un thread ServerRunnable che utilizza un selettore e tre thread di lavoro.

Ho cercato alcune informazioni al riguardo, come ho letto in passato che dovresti avere solo un thread per core del processore. Ecco.

Ma questo mi ha fatto pensare di recente, e dopo un po 'di ricerche ho trovato questo thread .

Dove, nei commenti sull'utente risposta accettato, Donal Fellows sottolinea quanto segue:

Have at most one CPU-bound thread per processor allocated to the application. IO-bound threads aren't a big problem (other than the memory they consume) and it's important to remember that apps can be restricted to only use a subset of the system's CPUs; after all, it's (usually) the user's/admin's computer and not the programmer's.

Con questo in mente, ho ragione di pensare che posso tranquillamente aumentare il numero di thread di selettore e thread di lavoro nel mio pool di thread.

Il thread del mio server legge l'input, elabora i dati in JSONObjects e li inserisce in una coda. I thread di lavoro prendono quindi JSONObjects dalla coda, controllano il tipo di oggetti che sono e quindi li inviano al database. Quindi c'è pochissimo lavoro computazionale in corso lì. È abbastanza sicuro per me aumentare il numero di thread qui, come in uso più thread ServerRunnable e più thread di lavoro? Dire di raddoppiare l'importo di ciascuno per esempio?

A cosa devo pensare quando considero qualcosa di simile?

    
posta bot_bot 19.03.2015 - 10:34
fonte

3 risposte

5

Non hai motivo di supporre quanti core della CPU ha il sistema degli utenti. La macchina di sviluppo potrebbe essere eseguita su una CPU a 4 core con nient'altro da fare, ma potrebbe anche essere spostata su una macchina virtuale single-core o su un server high-end a 32 core.

Per questo motivo non dovresti codificare il numero di CPU.

In Java, puoi usare ThreadPoolExecutor per delegare la gestione dei thread alla JVM. Di solito, i pacchetti di lavoro più piccoli vengono trasferiti all'esecutore in forma di oggetti che implementano Runnable e lasciano la decisione su quale thread esegue ogni eseguibile nel pool di thread. Nel tuo caso, i singoli JSONObjects sarebbero tali pacchetti di lavoro.

ThreadPoolExecutor consente di impostare il numero minimo e massimo di CPU che è consentito utilizzare. Ti consiglierei di rendere questo configurabile e predefinito su Runtime.getRuntime().availableProcessors() quando non viene fornita alcuna opzione di configurazione.

Indipendentemente dal fatto che il thread IO calcoli come un thread effettivo in relazione al carico della CPU dipende da ciò che effettivamente sta facendo. Quando riceve un'elevata larghezza di banda IO e ha un lavoro di analisi considerevole, potrebbe farlo. Ma non possiamo dirti questo senza profilare la tua applicazione in condizioni reali.

    
risposta data 19.03.2015 - 13:46
fonte
1

La potenza di elaborazione è la risorsa più scarsa in un computer. Mentre scrivo questo, la CPU più avanzata di cui sono a conoscenza ha 18 core e costa circa 6 grands . Questo limita il numero di thread a 18 se vuoi avere un vero parallelismo. Qualsiasi cosa di più è eccessiva, a meno che tu non stia scrivendo GUI o altre applicazioni non sensibili alla latenza.

Un thread singolo è in grado di gestire almeno diecimila connessioni. Ora immagina se volessi avere 10.000 thread, uno per ogni connessione?

Dai un'occhiata a questo articolo sui server ad alta disponibilità con CoralReactor per capire come un singolo thread può gestire migliaia di connessioni attraverso un demultiplexer e multiplexer.

Disclaimer: sono uno degli sviluppatori di CoralReactor.

    
risposta data 02.05.2015 - 18:40
fonte
1

Una delle cose che è fondamentale nella progettazione di un sistema multithreading è capire come suddividere il lavoro in un modo che mantenga il maggior numero possibile di core. Il tuo progetto proposto utilizza due tipi di thread che sono per lo più legati all'I / O e mette alcuni dei lavori computazionali su ciascuno.

Suggerirei di rendere separati i thread con I / O e di inserire gli elementi di elaborazione intensiva nel mezzo utilizzando tre tipi di thread:

  • Input - Legge l'input, lo inserisce in una coda di input e torna ad attendere ulteriori input. Sto partendo dal presupposto che l'input è un singolo flusso in cui non è pratico avere più lettori. Se i multipli funzionano, è sicuro aggiungere più di questi thread, fino al numero di canali forniti dall'ambiente di input. Il punto importante qui è che scaricando l'input su una coda il più velocemente possibile, il thread torna a leggere più input o viene limitato dall'I / O senza aggiungere alcun ritardo mentre viene elaborato, massimizzando la velocità di ingestione.

  • Elaborazione - Afferra gli elementi dalla coda di input, li converte in oggetti JSON, decide di quale tipo sono, prepara l'azione corretta del database e la inserisce in una coda di output. In altre parole, questo è tutto il lavoro parallelizzabile e ad alta intensità di CPU.

  • Output : rimuove gli elementi dalla coda di output e scrive il tuo database. Questi thread non eseguono quasi alcuna elaborazione e, come i thread di input, trascorrono la maggior parte del loro tempo in attesa del completamento degli I / O.

Il vantaggio di questo modello è che è possibile utilizzare lo stato delle code per prendere decisioni su come ottimizzare il sistema:

  • La crescita continua della lunghezza media della coda di input significa che non ci sono sufficienti thread di elaborazione per gestire il carico di input. La soluzione consiste nell'aggiungere più thread di elaborazione o, se non si dispone di core fisici, ottenere una macchina con più. (Meglio potrebbe essere un'altra macchina per prelevare parte del carico, ma questa è un'altra discussione.)

  • La crescita nella coda di output significa che si ha un collo di bottiglia nell'ottenere le scritture del database eseguite. Di solito ti interessano tutti i thread di output che il database può gestire in parallelo. Qualche altra cosa e stai solo scaricando il problema della sovrascrittura nel database. (Alcuni database sono migliori di altri per far fronte a questo, quindi se si scelgono più thread di output è una decisione che solo tu puoi prendere.)

risposta data 02.05.2015 - 20:17
fonte

Leggi altre domande sui tag