본문 바로가기

Computer Science/DB

DB Bulk Insert, Jmeter 부하테스트

안녕하세요, 오늘은 Issue Tracker 프로젝트를 진행하면서 10만건 이상의 데이터에서 비정상적으로 느린 API 응답을 어떻게 개선했는지 기록을 공유하고자 포스팅을 작성합니다. 

 

Spring Data JDBC로 Bulk Insert하기

 

우선 부하 상황을 만들기 위해서 Spring Data JDBC로 Dummy Data를 Insert했습니다. 이 때, Spring Data JDBC의   saveAll 메서드는 기본적으로 객체 하나마다 개별적인 INSERT 쿼리를 실행합니다. 이는 saveAll 메서드가 객체 컬렉션의 각 요소를 개별적으로 처리하고 영속화하기 때문입니다. 각 객체는 개별적으로 삽입되며, 객체의 상태에 따라 개별적인 INSERT 쿼리가 생성됩니다. 객체마다 I/O가 실행되면 속도가 굉장히 느려집니다. 동일 트랜잭션 내에서 INSERT 쿼리의 실행 개수를 배치 단위로 실행하도록 구성할 수 있습니다.

 

application.properties에 다음 설정을 추가하면 100개의 객체를 처리한 후에 INSERT 쿼리를 실행하게 할 수 있습니다.

spring.data.jdbc.repositories.flushSize=100

간단하게 dummy Data를 만드는 클래스를 아래와 같이 작성해서 주입했습니다.

 

public void insert() {
        for (int k = 0; k < 1000; k++) {
            List<Issue> issues = new ArrayList<>();
            for (int i = 0; i < 1000; i++) {
                issues.add(
                        new Issue(null, (long)2, 2, getRandomString(), true, LocalDateTime.now(),
                                null, null));
            }
            issueRepository.saveAll(issues);
            System.out.println(k);
        }
    }

    private static String getRandomString() {
        String source = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            int index = random.nextInt(source.length());
            sb.append(source.charAt(index));
        }
        return sb.toString();
    }

 

부하 테스트 - Jmeter란?

웹 어플리케이션의 성능 테스트를 위해 Apache Bench, Apache JMeter, nGrinder 등 여러 툴이 있습니다. 그 중에서 JMeter를 이용해서 테스트해보겠습니다.

 

JMeter는 GUI를 지원하며, HTTP, HTTPS, JDBC, TCP에 대한 테스트가 가능합니다.

 

1. JMeter 설치

 

Apache JMeter - Download Apache JMeter

Download Apache JMeter We recommend you use a mirror to download our release builds, but you must verify the integrity of the downloaded files using signatures downloaded from our main distribution directories. Recent releases (48 hours) may not yet be ava

jmeter.apache.org

위 링크에서 최신버전의 Binary 파일을 다운받습니다.

압축 해제한 후, bin 폴더에서 ./jmeter를 실행시키면 GUI가 실행되어 쉽게 사용할 수 있습니다.

 

2. 테스트 환경 설정하기

 

- Thread Group : 사용할 쓰레드 개수, 쓰레드 1개당 하나의 연결

- Sampler : 사용자의 행동 (GET, POST 등)

- Listener : 응답을 받아 검증, 그래프 등 처리를 담당

- Assertion : 응답 확인 방법 (응답 코드나 담긴 내용에 대한 테스트 작성 가능)

 

2.1 테스트 생성

 

File -> New -> Test Plan Name 설정

 

2.2 Thread Group 설정

 

2.1에서 만든 테스트 우클릭 후 Add, Threads, Thread Group 클릭

부하 상황 시 연결의 개수, 빈도를 지정해줍니다. 저는 100개의 연결이 1초에 2번 발생하도록 설정했습니다.

 

 

2.3 Sampler

 

다음으로 사용자의 행동을 정의합니다. Thread Group 우클릭, Add, Sampler, Http Request를 클릭합니다.

 

서버의 URL, Path, Port를 지정하여 요청을 보내는 Sampler를 생성할 수 있습니다.

 

여기에서 IP에 해당 서버의 IP 주소, Port Number, Request Method와 Path를 선택해주면 됩니다.

 

2.4 Listener

 

Sampler 요청의 Return을 처리해주는 Listener를 생성합니다.

2.3에서 만든 HTTP Request 우클릭, Add, Listener, View Results Tree, Summary Report, View Results in Table을 전부 클릭합니다.

 

2.5 Assertion

 

응답이 제대로 왔는지 검증하는 Assertion을 추가합니다. HTTP Request 우클릭, Add, Assertions, Response Assertion을 클릭합니다. Patterns to Test에 포함되어야하는 Pattern을 추가합니다. 저는 간단하게 milestone이라는 패턴이 포함되었으면 OK라고 정의했습니다.

 

 

설정이 완료되면, 상단 바의 초록 버튼으로 테스트를 실행하고, 오른쪽의 버튼으로 테스트 결과를 clear할 수 있습니다.

간단하게 실행 후 Summary Report를 확인해보겠습니다.

 

요청 당 평균 시간이 36807ms인데요.. 굉장히 오래걸려서 Error도 높습니다. 연결된 채 응답이 오지 않으면 타임아웃이 발생해서 에러가 발생하기 때문에 에러율이 높은 것입니다. 원인은 에러 로그를 확인했을 때 JDBC connection timeout이 발생하므로 현재로서는 슬로우 쿼리로 인한 지연으로 추정됩니다. 다음 포스팅부터는 개선하기 위해 CloudWatch로 구체적인 슬로우쿼리 로그를 확인하고, 테이블 구조 변경 및 인덱스 설정 등을 해보겠습니다.