여러 작업을 하나의 요청으로 처리할때 많은 시간이 소요되는 경우가 있습니다.
작업의 선후관계가 중요하지 않고 각각의 작업들이 독립적인 상황이라면 이를 비동기로 처리하여
요청에 대한 시간을 절약하는것이 좋은 방법이 될 수 있습니다.
저의 경우에도, 채팅을 하는 어플리케이션에서 소켓을 통해 상대방과 대화하고 상대방이 메세지를 안 읽은 상태이면
이를 푸시알림을 보내주게끔 구현을 했었습니다. 허나, 푸시알림을 보내는 과정에서 시간이 상당히 소요되어
채팅을 하는데 메세지가 2~3초 뒤에 표시되는 현상이 나타났습니다.
따라서 이를 비동기를 통해 메인쓰레드에서 소켓을 통해 채팅하고 DB에 메세지를 넣는 작업을 하고
새로운 쓰레드에서 푸시알림을 보내게끔하여 요청에 대한 응답을 빠르게 할 수 있었습니다.
이런식으로 비동기를 이용한다면 시간을 절약할 수 있습니다.
허나 작업이 서로 연관이 있고, 작업의 결과를 받아 결과값을 가지고 작업을 처리해야한다면 비동기는 사용할 수 없겠죠.
비동기는 작업이 서로 연관이 없고 독립적으로 실행될 수 있을때 사용을 하는게 바람직합니다.
스프링에서 비동기 작업은 @async 애노테이션을 통해 작업 할 수 있습니다.
xml 방식과 java config 방식 두가지가 있는데 두개 다 어떻게 하는지 알아보겠습니다.
config 설정
- xml 방식
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="10" />
<property name="queueCapacity" value="25" />
</bean>
<!-- messageSender 빈은 @Async애노테이션이 적용된 메서드가 포함된 클래스입니다. -->
<bean id="messageSender" class="[패키지].MessageSender">
<task:annotation-driven executor="taskExecutor" />
xml설정 파일에 위와 같이 빈설정과 <task:annotation-driven /> 에 executor="taskExecutor" 속성을 넣어준다.
ThreadPoolTaskExecutor 클래스를 통해 우리는 쓰레드 관련 설정을 할 수 있습니다.
corePoolSize는 기본 쓰레드 풀 생성 갯수를 설정하고,
maxPoolSize는 최대 쓰레드 풀 생성 갯수를 설정할 수 있고,
queueCapacity는 최대 쓰레드가 생성되어 있을때 대기하는 큐의 사이즈를 설정하는 것입니다.
- java config
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@EnableAsync
@Config
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
public class AsyncConfig implements AsyncConfigurer {
@Bean
public ThreadPoolTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(4);
scheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
return scheduler;
}
// @Async 메소드를 사용할 클래스
@Bean
public MessageSender messageSender() {
return new MessageSender();
}
@Override
public Executor getAsyncExecutor() {
return taskScheduler();
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
// TODO Auto-generated method stub
return null;
}
}
자 이제 설정을 끝났고 비동기를 사용할 클래스를 작성하겠습니다.
import org.springframework.scheduling.annotation.Async;
@EnableAsync
public class MessageSender {
@Async
public void myAsyncTask1() {
//처리할 작업 구현
}
@Async
public void myAsyncTask2() {
//처리할 작업 구현
}
@Async
public void myAsyncTask3() {
//처리할 작업 구현
}
@Async
public void myAsyncTask4() {
//처리할 작업 구현
}
}
위와 같은 형태에서 처리하고 싶은 작업이 있다면 본인이 구현을 하시면 됩니다.
그리고 사용할 때에 주의 사항이
사용할 클래스에서
@Resource
private messageSender MessageSender;
위와 같이 필드값을 줘서
message.myAsyncTask1();
이렇게 사용을 하시면 됩니다. 그러면 message.myAsyncTask1()에서 하는 작업은 비동기로 처리가 됩니다.
'Framework & Lib > 스프링' 카테고리의 다른 글
웹에디터 게시판 써머노트 스프링 웹서버에 이미지 첨부하기 (0) | 2021.06.20 |
---|---|
[스프링 시큐리티] 자동로그인 remember-me 쿠키 생성 커스터마이징 (0) | 2021.04.18 |
[스프링] logback 중복 제거 (0) | 2021.02.19 |
웹소켓 허트비트 heatbeat 설정(소켓 연결 상태확인) (0) | 2020.11.30 |
RecoverableDataAccessException 커넥션을 잃어버렸을때 에러 (0) | 2020.03.22 |