테스트 클래스를 일정 수 이상 묶어서 실행하면, 어느 정도 실행하다가 갑자기 JDBC Connection을 무한히 대기하는 현상
1
2
oracle.net.ns.NetException: Listener refused the connection with the following error:
ORA-12519, TNS:no appropriate service handler found.
1
select \* from v$resource\_limit where resource\_name = 'processes';
- 프로세스 수가 최대치에 육박하여 더 이상 요청을 처리할 수 없어 발생하는 문제. 커넥션 풀 close를 제대로 하지 않는 것으로 보임.
- HikariDataSource(==ConnectionPool)의 maximumPoolSize 기본값은 10인데, 이를 3으로 변경하고 수행하니 커넥션에 여유가 생겨 pending 걸리던 구간 통과하여 끝까지 TC 수행됨.
- 하지만 이는 임시방편이고 테스트 후 connection close를 자동으로 수행할 방법 필요함.
확인 결과, 아래와 같은 상황임.
- 테스트 클래스 마다 [DB는 초기화 하지 않고, Docker 컨테이너도 초기화 하지 않고,
TestDatabaseConfig
만 초기화 함] TestDatabaseConfig
가 매 테스트 클래스 마다 호출되면서 별도의HikariPool
을 생성함- 테스트가 종료되어도 이
HikariPool
이 가지고 있는 connection이 close 되지 않아서, 오라클에서 처리할 수 있는 최대 커넥션 수에 육박하면 pending- 모든 테스트가 종료된 후 마지막에 모든
HikariPool
을 몰아서 닫고 있다. - 각 테스트 마다
HikariDataSource
를 수동으로 DI 받아 cleanup에서 close() 호출하면 제대로 동작한다
- 모든 테스트가 종료된 후 마지막에 모든
1
2
3
4
2021-10-19 13:59:21.467 [Thread-12] INFO com.zaxxer.hikari.HikariDataSource - HIKARI\_POOL2021-10-19T13:58:32.584 - Shutdown initiated...
2021-10-19 13:59:21.467 [Thread-12] DEBUG com.zaxxer.hikari.pool.HikariPool - HIKARI\_POOL2021-10-19T13:58:32.584 - Before shutdown stats (total=3, active=0, idle=3, waiting=0)
2021-10-19 13:59:21.473 [Thread-25] INFO com.zaxxer.hikari.HikariDataSource - HIKARI\_POOL2021-10-19T13:58:40.102 - Shutdown initiated...
2021-10-19 13:59:21.473 [Thread-25] DEBUG com.zaxxer.hikari.pool.HikariPool - HIKARI\_POOL2021-10-19T13:58:40.102 - Before shutdown stats (total=3, active=0, idle=3, waiting=0)
이는 Spring TestContext Framework 가 “같은 설정에 대해서만” ApplicationContext
를 재사용 하기 때문임.
해결 방안 선택지
- 굳이 TestDatabaseConfig를 매 테스트 마다 호출할 필요가 없으니, 전 테스트에 걸쳐 딱 한 번만 호출하도록 수정
- 모든 TestClass가 같은
ApplicationContext
를 사용하도록 구성. 가능한가? - context 캐시를 활용할 수 있으므로 속도 이점이 있어서 제일 괜찮아 보이는 방법
- 하지만 테스트 마다 basePackage나 Bean 등을 별도로 지정하여 실행하는 경우라면? 모든 패키지에 대한 통합 context를 생성하지 않는 한, 잡 별로(TC별로)
ApplicationContext
가 다를 수 밖에 없다.
- 모든 TestClass가 같은
테스트 클래스 하나 끝나면, 자동으로 HikariPool 삭제 하도록 추가 설정- 하지만 이 경우, ApplicationContext 캐시를 재사용 할 때 HikariPool이 이미 닫혀있어 에러 발생할 듯
- 모든 통합 테스트에
@DiretiesContext
를 붙여 클래스가 끝날 때ApplicationContext
를 삭제하도록 변경- 2번과 비슷하지만 ApplicationContext 자체를 초기화 하는 것이라 잘 동작함.
- 초기화 시점을
AFTER_CLASS
로 두면 된다.
- 기본 context cache maximum size가 32이므로 이에 맞게 HikariPool size 또는 오라클 프로세스 수용치를 조정
- HikariPool Connection size를 3으로 조절하면, 32*3 = 96 이므로 기본 오라클 프로세스 max인 100 이하라서 수용 가능함.
- 또는 context cache maximum size를 줄이거나, 오라클 프로세스 max를 늘리는 방법도 가능.
1,2번은 사용할 수 없는 선택지이고 모든 TC에 DirtiesContext를 붙이는 것(3) 보다, context cache는 캐시대로 사용할 수 있도록 4번 방안으로 해결하는 것이 무난해 보임.
This post is licensed under CC BY 4.0 by the author.