Проблемы с потоками
Ниже приведены некоторые сценарии, которые указывают на наличие проблем с производительностью или другие проблемы со стабильностью в решении ThingWorx.
Много заблокированных потоков в течение длительного периода времени
Конфликты общих ресурсов
Длительное выполнение потоков
Этот раздел содержит обзор этих типов проблем.
Заблокированные потоки
Наличие множества заблокированных потоков в течение длительного периода времени указывает на высокую степень конфликтов ресурсов на уровне JVM или на потенциальную взаимоблокировку. Если множество потоков заблокировано и ожидает доступа к общему ресурсу, например к базе данных, выполнение операций пользователей обычно блокируется.
Серьезные конфликты иногда разрешаются самостоятельно. Например, при завершении большой операции записи в базу данных. Однако если потоки остаются заблокированными в течение длительного периода времени, это может быть связано со следующим:
Возникла ситуация взаимоблокировки, когда потоки блокируют друг друга.
Имеется одна блокирующая транзакция, выполнение которой не завершается в течение требуемого времени.
Для проверки на наличие такой проблемы можно выполнить следующие действия:
Поиск количества заблокированных потоков.
Проверьте, остается ли заблокированный на одном снимке поток заблокированным и на последующих снимках.
На следующем изображении показан заблокированный поток:
В этом примере заблокирована операция разархивирования в TWEventProcessor-10. Ожидается завершение другой операции разархивирования в потоке TWEventProcessor-9. Возможно, два пользователя разархивируют файлы одновременно в ThingWorx, и второй пользователь ожидает, пока первый завершит операцию. Обе операции обращаются к объекту 0x2f9a4f4, который заблокирован в TWEventProcessor-9.
Если к тому же заблокировано множество потоков процессора, могут возникать более серьезные проблемы со стабильностью работы сервера. Кроме того, в подсистеме обработки событий может отображаться увеличение числа активных потоков. Если сценарий блокировки не разрешить достаточно быстро, в ней также будет отображаться растущая очередь необработанных событий.
Конфликты общих ресурсов
Потоки базы данных и событий в ThingWorx могут создавать узкие места для производительности по следующим причинам.
Проверьте группы потоков C3P0PooledConnectionPoolManager и TWEventProcessor на наличие конфликтов. Большое количество заблокированных или активно работающих потоков в этих категориях может указывать на потенциально узкое место для производительности.
Если все потоки базы данных и событий заняты, в очереди на сервере могут накапливаться события.
Рассмотрим следующий пример. В этом случае поток событий блокирует все потоки соединителя базы данных. Поток событий 11 в стеке вызовов выполняет большую операцию обновления базы данных.
"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
Логику пользовательских сервисов, выполняющих эту операцию, можно оптимизировать, как показано в следующем примере:
"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)
Длительное выполнение потоков
Длительное выполнение потоков может указывать на необходимость оптимизации пользовательского кода в решении ThingWorx. Типичные пользовательские транзакции выполняются на уровне JVM быстро, за долю секунды или за несколько секунд. Однако наличие длительно выполняемого (например, более 10 минут) потока, включающего пользовательский код, может говорить о проблеме. Сделайте несколько снимков потоков в течение 10 минут, чтобы увидеть, сколько времени занимает выполнение операции в определенном потоке.
Например, снимки, сделанные в течение 60 минут, показывают одинаковый шаблон выполнения в одном и том же потоке:
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)

В этом примере поток выполняет сортировку таблицы данных. Операция сортировки продолжается, пока выполняется итерирование каждого элемента в большой таблице данных. Эту операцию можно оптимизировать так, чтобы она выполнялась один раз - в конце. Длительно выполняемые операции приводят к возникновению конфликтов на уровне памяти, уровне базы данных или в других серверных ресурсах. Поэтому очень важно выявлять и оптимизировать длительно выполняемые сервисы в пользовательском решении ThingWorx.
Было ли это полезно?