동기 (sync)
- 메소드를 실행시킴과 동시에 결과 값이 기대되는 경우, 요청을 보낸쪽에서 결과가 반환될 때까지 기다린다.
- 안전성과 실행순서가 보장된다.
- 느리다.
비동기 (async)
- 요청을 보낸 쪽이 아니라 응답을 주는 쪽에서 결과를 알려준다.
- 요청을 보낸 쪽은 응답이 올 때까지 다른일을 하고 있는다.
- 빠르다.
- 순서가 보장되지 않기 때문에 처리하기가 까다로울 수 있다.
- 비동기로 처리하면 백그라운드에서 해당 작업을 처리하는 것을 의미한다.
블로킹(blocking)
- 스레드에서 발생하는 대기현상
- 네트워킹을 해야하는 대상이 여럿이라면 블로킹 소켓의 경우 대상 개수만큼 스레드를 생성한다. (멀티 스레드)
- 스레드가 많아지면 각 스레드가 차지하는 호출 스택 자원과 컨텍스트 스위칭 비용이 많이 발생한다.
- 즉, 블로킹 매커니즘의 주요 특징은 I/O가 가득 수신할 때까지 주어진 스레드가 아무것도 하지 않는다고 가정하는 것이다. 이 경우 메서드가 제어권을 반환하지 않으므로 애플리케이션 플로우가 블록된다.
논블로킹(non-blocking)
- 소켓 시스템콜에 대해 네트워크 시스템이 즉시 처리할 수 없는 경우라도 제어권이 바로 리턴되어 프로그램이 블록되지 않게하는 소켓 모드이다.
- 통신 상대가 여럿이거나 여러 작업을 병행하려면 논블로킹 또는 비동기 모드를 사용해야 한다.
- 어떤 시스템콜이 성공적으로 실행될 때까지 계속 루프를 돌면서 확인한다.(폴링)
- 단일 스레드로 운영할 경우 순차 실행을 보장할 수 있지만, 시간이 오래걸리면 그만 큼 다른 채널의 이벤트를 수행하지 못한다. 이럴땐 멀티스레드로 구현해야 한다.
- 논블로킹 매커니즘은 I/O요청을 즉시 큐에 넣고 애플리케이션 플로우 제어를 반환한다. 요청은 나중에 커널에서 처리된다. (리액티브)
- 블로킹보다 구현이 어렵지만, 성능과 확장에 유리하다.
논블로킹 ≠ 비동기
- 논블로킹 환경에서 응답이 빨리 돌아오지 않는다면 API는 에러와 함께 복귀하고 다른 행동을 하지 않는다. 반면 비동기 환경에서는 API는 항상 즉시 복귀하지만 응답은 늦게 돌아오기도 한다.
- 즉, 논블로킹 매커니즘에서 함수가 호출되어 있어도 제어권이 반환되었으므로 다음 작업을 실행하고, 비동기 매커니즘에서는 함수호출을 스택에 남겨두고 함수호출을 대신하여 작업이 계속 이어진다. (다른 스레드에서!)
- 비동기는 병렬(parallel)에 가깝고, 논블로킹은 폴링(polling)에 가깝다.
문제점
- 많은 요청이 들어왔을 때 순차적으로 실행이 돼 속도가 느리고 서버에 과부화 가 걸린다고 생각
해결방안
- 데이터가 많을 시 로직이 다 수행 되는 데 시간이 많이 걸리므로 api 요청을 즉시 반환하고 제어권이 반환되었으므로 다음 작업을 실행하고, 비동기 매커니즘에서는 함수 호출을 스택에 남겨두고 함수 호출을 대신하여 작업이 계속 이어지게 함.(다른 쓰레드에서)
@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurerSupport {
// @Configuration : Spring설정 관련 Class로 @Component
//등록되어 Scanning될 수 있다.
// @EnableAsync : Spring method에서 비동기 기능을 사용가능하게 활성화 한다.
// CorePoolSize :기본 실행 대기하는 Thread의 수**
// MaxPoolSize :동시 동작하는 최대 Thread의 수
// QueueCapacity : MaxPoolSize초과 요청에서 Thread생성 요청시,
//해당 요청을 Queue에 저장하는데 이때 최대 수용 가능한 Queue의 수,
// Queue에 저장되어있다가 Thread에 자리가 생기면 하나씩 빠져나가 동작
// ThreadNamePrefix :생성되는 Thread접두사 지정
//크기가 제한된 큐에 작업이 가득 차면 집중 대응 정책 saturation policy가 동작한다.
// 1.집중 대응 정책은 ThreadPoolExecutor에 setRejectedExecutionHandler메소드를 사용해 설정할 수 있다.
//중단 정책(abort)
//기본적으로 사용하는 집중 대응 정책이며 execute메소드에서 RejectedExecutionException을 던진다.
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor =newThreadPoolTaskExecutor();
executor.setCorePoolSize(8);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(10000);
executor.setThreadNamePrefix("async-tread-");
executor.setRejectedExecutionHandler(newThreadPoolExecutor.AbortPolicy());
executor.initialize();
return executor;
}
}
결과
- 응답 속도는 엄청 나게 빨라 졌지만 @Async의 기본 반환이 void라 프론트에 반환해줘야 할 데이터가 반환 되지 않음.
- CompletableFuture<ResponseDto<LankRoundDto>> CompletableFuture을 사용하면 원하는 반환 값을 리턴 할 수 있다고 하여 사용
'항해 99(9기) > WIL' 카테고리의 다른 글
항해 99 (9기) 11주차 WIL 풀 텍스트 인덱스 검색 (0) | 2022.12.05 |
---|---|
항해 99 (9기) 10주차 WIL (0) | 2022.11.27 |
항해 99 (9기) 9주차 WIL DB 실행 계획 (1) | 2022.11.21 |
항해 99 (9기) 8주차 WIL (0) | 2022.11.14 |
항해 99 (9기) 7주차 WIL (0) | 2022.11.06 |