비동기 통신: 자료를 일정한 크기로 정하여 순서대로 전송하는 자료의 전송방식(참고 : 비동기 전송방식)

graph LR subgraph Sync C1[Client 1]-->|Request|T1[Thread 1] T1[Thread 1]-->|Response|C1[Client 1] end subgraph Async C2[Client 2]-->|Request|T2[Thread 2] T2[Thread 2]-->|Response|C2[Client 2] T2[Thread2]-.->|Async|T3[Thread3] end

언제 사용하면 좋을까?

  • 요청이 긴 경우
  • 로그 처리
  • 푸시 처리

Dependency

Spring 3.1 이후에 사용 가능 하다. (spring-context에 포함되어 있다.)

1
2
3
4
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
testCompile('org.springframework.boot:spring-boot-starter-test')
}

Config

@EnableAsync만 추가하면 기본적인 설정은 끝이다.
하지만, 기본값인 SimpleAsyncTaskExecutor 클래스는 매번 Thread를 만들어내는 객체이기 때문에 Thread Pool이 아니다. Thread Pool을 설정해기 위해 AsyncConfigurerSupport를 상속받아 재구현하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurerSupport {

@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("heowc-async-");
executor.initialize();
return executor;
}
}

Service & Controller

Service

비동기 작업을 하기 위한 메소드에 @Async를 추가하면 된다. 만약 callback이 필요하다면, Future 클래스 등의 객체로 감싸서 반환하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Service
public class BasicServiceImpl implements BasicService {

private static final Logger logger = Logger.getLogger(BasicServiceImpl.class);

@Async
@Override
public void onAsync() {
try {
Thread.sleep(1000);
logger.info("onAsync");
} catch (InterruptedException e) {
e.printStackTrace();
}
}

@Override
public void onSync() {
try {
Thread.sleep(1000);
logger.info("onSync");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Controller

Test Case로는 비동기를 확인할 수 없기 때문에(?) HTTP 요청으로 이를 확인해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@RestController
public class BasicController {

@Autowired
private final BasicService service;

private static final Logger logger = Logger.getLogger(BasicController.class);
@GetMapping("/async")
public String goAsync() {
service.onAsync();
String str = "Hello Spring Boot Async!!";
logger.info(str);
logger.info("==================================");
return str;
}

@GetMapping("/sync")
public String goSync() {
service.onSync();
String str = "Hello Spring Boot Sync!!";
logger.info(str);
logger.info("==================================");
return str;
}
}
결과
1
http://localhost:8080/async
1
2
3
~ : Hello Spring Boot Async!!
~ : ==================================
~ : onAsync


1
http://localhost:8080/sync
1
2
3
~ : onSync
~ : Hello Spring Boot Sync!!
~ : ==================================

참고