Post

테스트 클래스를 일정 수 이상 묶어서 실행하면, 어느 정도 실행하다가 갑자기 JDBC Connection을 무한히 대기하는 현상

1
2
3
4
oracle.net.ns.NetException: Listener refused the connection with the following error:
ORA-12519, TNS:no appropriate service handler found.

1
2
select \* from v$resource\_limit where resource\_name = 'processes';

  • 프로세스 수가 최대치에 육박하여 더 이상 요청을 처리할 수 없어 발생하는 문제. 커넥션 풀 close를 제대로 하지 않는 것으로 보임.
  • HikariDataSource(==ConnectionPool)의 maximumPoolSize 기본값은 10인데, 이를 3으로 변경하고 수행하니 커넥션에 여유가 생겨 pending 걸리던 구간 통과하여 끝까지 TC 수행됨.
  • 하지만 이는 임시방편이고 테스트 후 connection close를 자동으로 수행할 방법 필요함.

확인 결과, 아래와 같은 상황임.

  1. 테스트 클래스 마다 [DB는 초기화 하지 않고, Docker 컨테이너도 초기화 하지 않고, TestDatabaseConfig만 초기화 함]
  2. TestDatabaseConfig가 매 테스트 클래스 마다 호출되면서 별도의 HikariPool을 생성함
  3. 테스트가 종료되어도 이 HikariPool이 가지고 있는 connection이 close 되지 않아서, 오라클에서 처리할 수 있는 최대 커넥션 수에 육박하면 pending
    • 모든 테스트가 종료된 후 마지막에 모든 HikariPool을 몰아서 닫고 있다.
    • 각 테스트 마다 HikariDataSource를 수동으로 DI 받아 cleanup에서 close() 호출하면 제대로 동작한다
1
2
3
4
5
6
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를 재사용 하기 때문임.

해결 방안 선택지

  1. 굳이 TestDatabaseConfig를 매 테스트 마다 호출할 필요가 없으니, 전 테스트에 걸쳐 딱 한 번만 호출하도록 수정
    • 모든 TestClass가 같은 ApplicationContext를 사용하도록 구성. 가능한가?
    • context 캐시를 활용할 수 있으므로 속도 이점이 있어서 제일 괜찮아 보이는 방법
    • 하지만 테스트 마다 basePackage나 Bean 등을 별도로 지정하여 실행하는 경우라면? 모든 패키지에 대한 통합 context를 생성하지 않는 한, 잡 별로(TC별로) ApplicationContext가 다를 수 밖에 없다.
  2. 테스트 클래스 하나 끝나면, 자동으로 HikariPool 삭제 하도록 추가 설정
    • 하지만 이 경우, ApplicationContext 캐시를 재사용 할 때 HikariPool이 이미 닫혀있어 에러 발생할 듯
  3. 모든 통합 테스트에 @DiretiesContext를 붙여 클래스가 끝날 때 ApplicationContext를 삭제하도록 변경
    • 2번과 비슷하지만 ApplicationContext 자체를 초기화 하는 것이라 잘 동작함.
    • 초기화 시점을 AFTER\_CLASS로 두면 된다.
  4. 기본 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.