[Java] Tomcat 스레드 갯수에 따른 성능 테스트

gyu·2024년 5월 26일

Tomcat의 스레드 수에 따른 성능 테스트를 Apache Jmeter로 확인해보자.

테스트 방법

  • Tomcat의 스레드 수를 200개, 500개, 1000개로 변경해가면서 1초간 Sleep 쿼리를 수행하는 특정 컨트롤러를 호출해본다.
  • 부하를 발생시키기 위해 Apache Jmeter의 Thread Group 속성은 다음과 같이 지정한다.
  • Number of Threads: 가상 사용자 수 설정 (5000명의 사용자)
  • Ramp-up period: Number of Thread 만큼의 스레드를 몇초에 걸쳐서 만들지 설정하는 옵션 (1초)
  • Loop Count: 스레드의 반복횟수 (1번 반복)

Controller 구성 및 호출 테스트

@RestController
public class JdbcController {

    @Autowired
    private JdbcRepository jdbcRepository;

    @GetMapping("/jdbc")
    public String test() throws Exception {
        jdbcRepository.executeSleepQuery();
        return "test";
    }
}

@Repository
public class JdbcRepository {

    private JdbcTemplate jdbcTemplate;

    @Autowired
    public JdbcRepository(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public void executeSleepQuery() throws Exception {
        jdbcTemplate.execute("SELECT SLEEP(1)");
    }
}

1초 Sleep 쿼리 실행 후 문자열을 반환하는 컨트롤러를 1개 구성하였다.
Hikari CP 커넥션 관련 설정은 다음과 같이 설정하였다.

# Connection 최대 갯수 (30개)
spring.datasource.hikari.maximum-pool-size=30

# Connection 점유 대기 최대 시간 (30초)
spring.datasource.hikari.connection-timeout=30000

테스트 결과

스레드 갯수: 200개

  • 소요시간: 2분 50초
  • Throughput(초당 처리량): 29.4

스레드 갯수: 500개

  • 소요시간: 1분 27초
  • Throughput(초당 처리량): 57.4

스레드 갯수: 1,000개

  • 소요시간: 2분 2초
  • Throughput(초당 처리량): 41
  • Error 발생비율: 27.4%

스레드 갯수가 500개인 환경에 비해 처리량이 낮고 27.4%의 에러가 발생한 것을 확인할 수 있다.

부하 테스트 실행 후 약 30초뒤에 콘솔에서 위와 같은 에러 메시지가 반복적으로 기록되고 있었는데, 이러한 결과가 발생한 이유는 다음과 같다.

  • maximum-pool-size를 30으로 설정했으므로 커넥션 풀에는 30개의 커넥션이 존재한다.
  • 커넥션을 획득하지 못하고 대기시간이 connection-timeout에 설정한 30초를 초과한 스레드가 존재하기 때문에 SQLTransientConnectionException이 발생한다.

해결방법

1. Connection pool 사이즈를 늘린다.
더 많은 Connection pool 사이즈를 갖게되면 스레드의 대기시간이 줄어들게 되고 connection timeout이 발생하기 전에 커넥션을 획득할 수 있으므로 문제를 해결할 수 있다.

다만 너무 크게 설정하면 그만큼 커넥션을 미리 생성해서 갖고 있으므로 리소스 낭비가 될 수 있으며, 트래픽이 증가한다면 커넥션 고갈현상이 동일하게 발생하므로 무조건적인 해결방법은 아니라고 볼 수 있다.

2. Connection timeout 시간을 늘린다.
Connection timeout 시간을 늘리면 이전보다 대기하는 시간이 길어지게 되므로 timeout이 발생하기 전에 커넥션을 획득하게 되면서 문제를 해결할 수 있다.
하지만 그만큼 대기시간이 증가하게 되어 응답시간이 늦어지는 단점이 있다.

3. Tomcat 스레드 수를 환경에 맞게 적절하게 설정한다.
Tomcat 스레드 수를 너무 적게 설정하면 다중 사용자 환경에서 처리시간이 늦어질 것이고
위 예제처럼 너무 많이 설정하면 잦은 Context Switching이 발생하며, SQLTransientConnectionException 발생 확률이 높아지기 때문에 애플리케이션의 상황에 따라
적절하게 설정하는 것이 중요하다.

결론

  • 스레드는 무조건 많다고 좋은 것이 아니다.
  • 애플리케이션의 동시 사용자 수가 얼마나 되는지, I/O 작업 비중이 어느정도 되는지에 따라 거기에 맞는 스레드 풀, 커넥션 풀을 설정해야 여러가지 문제(메모리 부족, Connection timeout, DeadLock 등)를 방지할 수 있다.

0개의 댓글