반응형

일정 시간마다 데이터를 받아와서 코드 테이블을 동기화 시켜야하는 프로세스가 있었다.

1분마다 돌아가도록 cron설정이 되어 있었고, 쿼츠가 동작하면 rest api형태로 데이터를 전달해주고 수신서버는 해당 데이터를 기반으로 delet -> insert 해주는 간단한 프로세스였다.

 

문제는 수신서버의 로직이였는데, insert할 데이터가 복잡하지 않았지만 2천개 가량의 데이터를 집어넣는데 30초가 넘게 소요되었다.

결국 1분마다 처리를 하다보니 코드는 약 20초간만 최신데이터를 쓸 수 있고, 나머지 시간은 제대로 채워지지 않은 데이터를 보게 되는 현상이였다.

 

추가적으로 rest api로 구성된 로직에서 request후 response가 안오면 뭔가 처리가 있어야하지만 에러상황이 발생하게 되었고, request를 요청한곳에서는 무기한으로 기다리는 현상으로 보였다.

rest api의 타임아웃 처리와 스케줄러 동작시간을 1분에서 5분정도로 변경하고 insert로직을 개선해야했다.

 

HttpPost timeout 설정

HttpPost post = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom()
  .setSocketTimeout(10*1000)
  .setConnectTimeout(10*1000)
  .setConnectionRequestTimeout(60*1000)
  .build();

post.setConfig(requestConfig);

RequestConfig 설정을 추가해주었다.

 

 

 

단일 INSERT 문제가 되었던 기존 로직

xxx.java

newList.forEach(data -> {
	try {
		mapper.insertOrgCode(data);
	} catch (Exception e) {
		e.printStackTrace();
	}
});

 

xxx.mapper

<insert id="insertOrgCode" parameterType="hashmap">
    INSERT INTO TB_TC998_CODE (
        GROUP_CD, CD, PARNTS_CD, CD_NM, DEPTH, REG_DATE
    ) VALUES (
         #{GROUP_CD},
         #{CD},
         #{PARNTS_CD},
         #{CD_NM},
         #{DEPTH},
         GETDATE()  
    )
</insert>

아래와같이 sublist를 통하여 잘라서 foreach를 통해 다량 등록을 하도록 변경하였다.

 

개선안

xxx.java

while(newList.size() > 0) {
	try {
		int toIndex = 200;
		if(toIndex > newList.size()) {
			toIndex = newList.size();
		}
		
		//insert시작
		param.put("list", newList.subList(0, toIndex));
		int result = mapper.insertOrgCode(param);
		
		
		if(result == toIndex) {
			//insert끝나면 list 삭제
			for(int j=0; j<toIndex; j++) {
				newList.remove(0);
			}
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
}

MAX값이 너무 커도 오류가 발생해서 200개로 제한을 두었다.

 

xxx.mapper

<insert id="insertOrgCode" parameterType="hashmap">
	INSERT INTO TB_TC998_CODE (
		GROUP_CD, CD, PARNTS_CD, CD_NM, DEPTH, REG_DATE
	) VALUES
	<foreach collection="list" item="item" separator=" , " >
        (
            #{item.GROUP_CD},
            #{item.CD},
            #{item.PARNTS_CD},
            #{item.CD_NM},
            #{item.DEPTH},
            GETDATE()  
        )
	</foreach>
</insert>

처리 후 동작시간을 비교해보았는데, 로컬에서도 심각하게 차이가 발생했다.

아래는 start, end 시간을 측정해본 콘솔 창이다.

43초대 2초... 심각하게 차이가 발생한다.

 

다량의 insert를 해야하는 경우가 있으면 mybatis foreach 구문을 사용하도록 하자!

반응형