매일 조금씩

[스프링] 비동기 서비스 구현하기 (@Async 사용) 본문

Spring Framework

[스프링] 비동기 서비스 구현하기 (@Async 사용)

mezo 2022. 2. 24. 20:18
728x90
반응형

구현된 서비스는..

pdf 파일을 업로드 하면, 

1. 원본파일을 저장하고

2. 각 페이지를 image와 thumbnail로 변환한다. 

 

위의 1,2번을 완료 해야 스프링 컨트롤러에서 응답하도록 구현을 했는데..

2번의 과정이 너무 오래 걸려 응답이 늦어졌다. 

 

따라서 1번까지만 하고 응답하고, 2번은 비동기로 구현하게 되었다. 

 

방법은 간단하다. 

  1. @EnableAsync로 비동기 기능을 활성화
  2. 비동기로 동작을 원하는 메소드(public 메소드)에 @Async 어노테이션을 붙여준다.

 

 

 


@Async 어노테이션을 사용해서 비동기 서비스 만들기

 

1. springboot에서 Async 비동기 기능 활성화 및 thread pool 설정

아래와 같이 java config 파일을 만든다. 

> config > AsyncConfig.java 

package com.tmax.meeting.document.config;

import java.util.concurrent.Executor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurerSupport {

  @Bean
  public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(10);
    executor.setMaxPoolSize(50);
    executor.setQueueCapacity(100);
    executor.setThreadNamePrefix("pdf-to-png-async-");
    executor.initialize();
    return executor;
  }
}
  • @EnableAsync : spring의 메소드의 비동기 기능을 활성화 해준다.
  • ThreadPoolTaskExecutor로 비동기로 호출하는 Thread 대한 설정을 한다.
    • corePoolSize: 기본적으로 실행을 대기하고 있는 Thread의 갯수
    • MaxPoolSise: 동시 동작하는, 최대 Thread 갯수
    • QueueCapacity : MaxPoolSize를 초과하는 요청이 Thread 생성 요청시 해당 내용을 Queue에 저장하게 되고, 사용할수 있는 Thread 여유 자리가 발생하면 하나씩 꺼내져서 동작하게 된다.
    • ThreadNamePrefix: spring이 생성하는 쓰레드의 접두사를 지정한다.

 

 

 

2. @Async를 적용한 service 만들기

비동기로 처리하고자하는 메서드 위에 @Async를 붙인다.

 

> service > DocServiceImpl.java

  @Async
  @Override
  public void makePngAndThumbnails(ConverterUtil converter, Document toSave) throws IOException {
    converter.pdfToPng();
    converter.makeThumbnails();

    toSave.setConverted(true);
    toSave.setPageNum(converter.getNumberOfPages());

    ResponseModel converted = updateDocument(toSave);
    
    simpMessagingTemplate
    .convertAndSend("/document/topic/room/" + converted.getRoomId(),
        WebSocketMessage.builder()
            .type("document_create")
            .message("A new document has been uploaded.")
            .uploadedBy(converted.getUploadedBy())
            .build());
  }

@Async는 @Service가 붙은 클래스 안에서만 유효하다. 

처음에 util 클래스에서 붙여서 썼더니 구현이 되지않았다.. ㅜ

 

비동기로 구현된 2번이 완료되면 프론트에 웹소켓으로 메세지를 날리도록 구현하였다. 

728x90
반응형