Problemi con i thread
Di seguito sono riportati alcuni degli scenari che indicano problemi di prestazioni o di stabilità nell'applicazione ThingWorx.
Numero elevato di thread bloccati per un periodo di tempo lungo
Conflitto di risorse condivise
Thread a esecuzione prolungata
In questa sezione viene fornita una panoramica di questi tipi di problemi.
Thread bloccati
Se molti thread restano bloccati per un periodo di tempo lungo, significa che è presente un elevato conflitto di risorse a livello di JVM o un potenziale blocco critico. In genere, quando un numero elevato di thread è bloccato e in attesa di una risorsa condivisa, ad esempio l'accesso al database, gli utenti non riescono a eseguire operazioni.
L'elevato conflitto talvolta si risolve da solo. Ad esempio, un'operazione di scrittura di database di grandi dimensioni che viene completata Tuttavia, se i thread rimangono bloccati per un periodo di tempo lungo, potrebbe essersi verificata una delle situazioni descritte di seguito.
Una situazione di blocco critico, ovvero i thread si bloccano a vicenda secondo uno schema circolare.
Una singola transazione di blocco non completa l'elaborazione nel tempo necessario.
È possibile verificare il problema nei modi descritti di seguito.
Cercando il numero di thread bloccati.
Verificando se il thread bloccato in un'istantanea resta bloccato nelle istantanee successive.
L'immagine seguente mostra un thread bloccato:
In questo esempio l'operazione di decompressione in TWEventProcessor-10 è bloccata. È in attesa del completamento di un'altra operazione di decompressione nel thread TWEventProcessor-9. È possibile che due utenti stiano effettuando contemporaneamente una decompressione file in ThingWorx e il secondo utente deve attendere che il primo termini l'operazione. Entrambe le operazioni accedono all'oggetto 0x2f9a4f4 bloccato in TWEventProcessor-9.
Se sono bloccati anche molti thread del processore di eventi, possono esserci problemi di stabilità del server più importanti. Inoltre il sottosistema di elaborazione degli eventi potrebbe mostrare un aumento del numero di thread attivi. Se lo scenario bloccato non viene risolto rapidamente, anche la coda di eventi non elaborati aumenta.
Conflitto di risorse condivise
I thread di database e degli eventi in ThingWorx possono costituire un collo di bottiglia delle prestazioni per i motivi riportati di seguito.
Verificare il conflitto per i gruppi di thread C3P0PooledConnectionPoolManager e TWEventProcessor. Un numero elevato di thread bloccati o che lavorano attivamente in queste categorie può indicare un potenziale collo di bottiglia nelle prestazioni.
Se tutti i thread di database e degli eventi sono occupati, potrebbero essere presenti eventi in coda sul server.
Si consideri l'esempio che segue. In questo caso un thread di evento blocca tutti i thread del connettore di database. Il thread di evento 11 nello stack di chiamate sta eseguendo un'operazione di aggiornamento del database di grandi dimensioni.
"C3P0PooledConnectionPoolManager[identityToken->2v1py89n68drc71w36rx7|68cba7db]-HelperThread-#7" tid=0xa0 in BLOCKED
Blocked: 414717[-1ms], Waited: 416585[-1ms]
User CPU: 5s320ms
at java.lang.Object.wait(Native Method)
- waiting on <0x56978cbf> (a com.mchange.v2.async.ThreadPoolAsynchronousRunner), held by TWEventProcessor-11
"C3P0PooledConnectionPoolManager[identityToken->2v1py89n68drc71w36rx7|68cba7db]-HelperThread-#6" tid=0x9f in BLOCKED
Blocked: 415130[-1ms], Waited: 416954[-1ms]
User CPU: 5s530ms
at java.lang.Object.wait(Native Method)
- waiting on <0x56978cbf> (a com.mchange.v2.async.ThreadPoolAsynchronousRunner), held by TWEventProcessor-11
La logica dei servizi personalizzati che eseguono l'operazione può essere ottimizzata, come illustrato nell'esempio riportato di seguito.
"TWEventProcessor-11" tid=0x92 in RUNNABLE
Blocked: 3913[-1ms], Waited: 37924[-1ms]
User CPU: 45s430ms
at com.thingworx.persistence.common.sql.SqlDataTableProvider.updateEntry(SqlDataTableProvider.java:13)
at com.thingworx.persistence.TransactionFactory.createDataTransactionAndReturn(TransactionFactory.java:155)
at com.thingworx.persistence.common.BaseEngine.createTransactionAndReturn(BaseEngine.java:176)
Thread a esecuzione prolungata
I thread a esecuzione prolungata indicano che potrebbe essere necessario ottimizzare il codice personalizzato nell'applicazione ThingWorx. Le transazioni utente tipiche vengono completate rapidamente a livello di JVM, entro pochi millesimi di secondo o qualche secondo. Tuttavia un thread a esecuzione prolungata, ad esempio oltre 10 minuti, che include un codice personalizzato può indicare un problema. Raccogliere diverse istantanee di thread per un intervallo di 10 minuti per verificare quanto impiega l'esecuzione di un'operazione su un thread specifico.
Ad esempio, un'acquisizione eseguita in un intervallo di 60 minuti mostra lo stesso schema di esecuzione sullo stesso thread:
http-nio-8443-exec-25" tid=0xc7 in RUNNABLE
Blocked: 750[-1ms], Waited: 8866[-1ms]
User CPU: 1h35m
- synchronizer <0x35153c2f> (a java.util.concurrent.ThreadPoolExecutor$Worker)
at com.thingworx.types.data.sorters.GenericSorter.compare(GenericSorter.java:93)
at com.thingworx.types.data.sorters.GenericSorter.compare(GenericSorter.java:20)
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:360)
at java.util.TimSort.sort(TimSort.java:234)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1454)
at java.util.Collections.sort(Collections.java:175)
at com.thingworx.types.InfoTable.quickSort(InfoTable.java:722)

Nell'esempio il thread esegue un ordinamento su una infotable. L'operazione di ordinamento continua durante l'iterazione in ogni elemento di una infotable di grandi dimensioni. È possibile ottimizzare l'operazione in modo che venga eseguita una sola volta alla fine. Le operazioni a esecuzione prolungata creano un conflitto a livello di memoria, a livello di database o in altre risorse del server. Pertanto è importante identificare e risolvere i servizi a esecuzione prolungata nell'applicazione ThingWorx personalizzata.