스레드 문제
다음은 ThingWorx 응용 프로그램의 성능 또는 기타 안정성 문제를 나타내는 몇 가지 시나리오입니다.
오랜 기간 차단된 많은 스레드
공유 리소스 경합
장기 실행 스레드
이 단원에서는 이러한 유형의 문제에 대해 간략하게 설명합니다.
차단된 스레드
오랜 기간 차단된 많은 스레드는 JVM 수준의 높은 리소스 경합 또는 잠재적 교착 상태를 표시합니다. 많은 스레드가 차단되고 공유 리소스를 기다리는 경우(예: 데이터베이스 액세스) 사용자가 일반적으로 작업을 수행할 수 없도록 차단됩니다.
경합이 높을 때 자체적으로 해결되는 경우도 있습니다. 예를 들어, 대규모 데이터베이스 쓰기 작업이 완료된 경우입니다. 그러나 스레드가 오랜 기간 차단된 상태를 유지하는 경우 다음과 같은 문제가 있을 수 있습니다.
교착 상태 상황이 있을 수 있습니다. 즉, 스레드가 순환 패턴으로 서로 잠깁니다.
또는 필요한 시간에 처리를 완료하지 않는 단일 차단 트랜잭션이 있을 수 있습니다.
다음과 같은 방법으로 이 문제를 확인할 수 있습니다.
차단된 스레드 수를 검색합니다.
한 스냅샷에서 차단된 스레드가 후속 스냅샷에서 차단된 상태로 유지되는지 확인합니다.
다음 이미지는 차단된 스레드를 보여줍니다.
이 예에서는 TWEventProcessor-10의 압축 풀기 작업이 차단되어 있습니다. 다른 압축 풀기 작업이 TWEventProcessor-9 스레드에서 완료되기를 기다리고 있습니다. 두 사용자가 ThingWorx에서 동시에 파일 압축을 푸는 것은 가능하며, 두 번째 사용자는 첫 번째 사용자가 작업을 마칠 때까지 기다립니다. 두 작업 모두 TWEventProcessor-9에서 잠긴 객체 0x2f9a4f4에 액세스합니다.
많은 이벤트 프로세서 스레드도 차단되는 경우 서버 안정성 문제가 더 클 수 있습니다. 또한 이벤트 처리 하위 시스템에서 활성 스레드 수가 증가하는 것을 볼 수 있습니다. 차단된 시나리오가 빠르게 해결되지 않는 경우 처리되지 않은 이벤트의 증가하는 대기열도 표시합니다.
공유 리소스 경합
ThingWorx의 데이터베이스 및 이벤트 스레드는 다음과 같은 이유로 인해 성능 병목 현상이 될 수 있습니다.
스레드의 C3P0PooledConnectionPoolManagerTWEventProcessor 그룹에 대한 경합을 확인합니다. 차단된 스레드 또는 이러한 카테고리에서 활발하게 작동하는 스레드의 수가 많은 경우 성능 병목 현상을 나타낼 수도 있습니다.
모든 데이터베이스 및 이벤트 스레드가 이미 다 사용된 경우 서버의 대기열에 추가된 이벤트가 있을 수 있습니다.
다음 예제를 참고하십시오. 이 경우 이벤트 스레드는 모든 데이터베이스 커넥터 스레드를 차단합니다. 호출 스택의 이벤트 스레드 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 수준에서 1초 미만 또는 몇 초 내에 신속하게 완료됩니다. 그러나 사용자 정의 코드와 관련하여 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 응용 프로그램에서 장기 실행 서비스를 식별하고 해결하는 것이 중요합니다.