업무와 관련해서 비지니스 로직 응답 속도 개선을 위해 만든 병렬처리모듈을 소개한다.
아래 모듈을 실무에 적용하여 최대 1/4 정도의 응답 속도 감소 효과를 볼 수 있었다. (4s -> 1s)
1. 개요
- 선후 관계가 없는 비지니스 로직의 처리 응답 속도를 개선하기 위해 자바 concurrency 및 reflection을 이용해 병렬로 처리하는 모듈 개발.
2. 소스 레파지토리 : https://github.com/khparkDev/ParallelExecutor
- 응답을 받을 수 있는 Callback Executor와 응답을 받지 않는 DefaultExecutor 두 클래스로 구분해놓았다.(TestMain.java에 사용 방법을 기술해놓았음)
3. 주요 로직
* 작업 추가 및 실행
protected void executeWorkerThread() {
executor = Executors.newFixedThreadPool(taskMap.size());
taskMap.entrySet().parallelStream().forEach(
tm -> {
futureMap.put(tm.getKey(), executor.submit(new ParallelWorkerThread(taskMap.get(tm.getKey()))));
executorLogger.setStartTimeTask(tm.getKey());
});
futureMap.entrySet().parallelStream().forEach(
fm -> {
try {
result.put(fm.getKey(), futureMap.get(fm.getKey()).get(TIMEOUT_SEC, TimeUnit.SECONDS));
executorLogger.setEndTimeTask(fm.getKey());
} catch (Exception e) {
LOGGER.error("# executeParallelTask : ", e);
}
});
}
* 실제 작업 수행 쓰레드 클래스
public Object call() throws Exception {
Method[] classMethods = classObject.getClass().getDeclaredMethods();
List methodList = Stream.of(classMethods).parallel()
.filter(method -> method.getName().contains(methodName) && method.getParameterTypes().length == taskParamClassType.length)
.collect(Collectors.toList());
if (taskParamClassType.length == 0) {
return methodList.get(0).invoke(classObject);
}
for (Method targetMethod : methodList) {
Class[] methodParams = targetMethod.getParameterTypes();
for (int i = 0; i < taskParamClassType.length; i++) {
String taskParamTypeName = taskParamClassType[i].getSimpleName().toLowerCase();
String methodParamTypeName = methodParams[i].getSimpleName().toLowerCase();
if (taskParamTypeName.contains(methodParamTypeName)) {
targetMethod.setAccessible(true);
return targetMethod.invoke(classObject, taskParam);
}
}
}
return EMTPY_OBJECT;
}
4. 실행 결과 - 개별 작업들의 실행 시간 출력 및 가장 오래 걸린 시간(실제로 병렬처리가 수행된 시간)을 보여준다
[2015-11-09 20:43:02] [DEBUG] TestMain.main[24]
[2015-11-09 20:43:02] [DEBUG] SampleService.testService[34] testService = {true, C, 1, 1}
[2015-11-09 20:43:02] [DEBUG] SampleService.testService[24] testService = {msg = message test!}
[2015-11-09 20:43:02] [DEBUG] SampleService.testService[13] testService
[2015-11-09 20:43:02] [DEBUG] SampleService.testService[29] testService = {10, 12.2,345.123}
[2015-11-09 20:43:02] [DEBUG] SampleService.testService[19] testService = {model.getName() = testName}
[2015-11-09 20:43:02] [DEBUG] ExecutorLogger.prettyPrint[54]
--------------------------------------------------
taskName = testService0 , execute time = 100 ms
taskName = testService2 , execute time = 100 ms
taskName = testService1 , execute time = 140 ms
taskName = testService4 , execute time = 100 ms
taskName = testService3 , execute time = 100 ms
--------------------------------------------------
Total Execute time = 140 ms
--------------------------------------------------