티스토리 뷰

Sync/Async, Blocking/Non-Blocking

Multi Thread WAS vs Single Thread WAS

  • 사전지식 : Process vs Thread
  • 멀티 스레드로 잘 서비스하던 어느날, 갑자기 10k(1만명)를 동시에 서비스할 일이 생겼다. 일명 C10K Problem. 1만명 동접이 가능하려면 어떻게 해야할까? 자바의 대표 멀티 스레드 서버인 톰캣은 기본 max-thread가 200밖에 되지 않는다 !
  • 10k를 멀티 스레드로 구현할 경우, 가장 큰 문제는 Context-Switching 비용
  • -> Single Thread + Non-Blocking + Async 구조면 가능하지 않을까? 이들에 대해 알아보자.

애플리케이션 개발에서의 sync vs async

  • 먼저, [애플리케이션 개발에서의 sync vs async]와 [Sync/Async, Blocking/Nonblocking에서의 sync vs async]는 다르다

  • 물건 주문에 0.5초 메일발송에 2초 걸린다면, sync는 mailService.sendMail();을 호출하고 기다려 0.5 + 2 = 2.5초 걸린다. 반면 메일발송을 async처리하면 기다리지않고 바로 리턴해 0.5+a초 걸린다.

  • Spring의 비동기 처리 : @Async, @EnableAsync

    void order() {
      // 주문 처리 코드 생략
      mailService.sendMail();
    }
    public class MailService {
      @Async
      void sendMail() {
          // 메일 발송
      }
    }
    @Configuration
    @EnableAsync
    public class SpringAsyncConfig {
      @Bean(name = "threadPoolTaskExecutor")
      public Executor threadPoolTaskExecutor() {
          ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
          taskExecutor.setCorePoolSize(3);
          taskExecutor.setMaxPoolSize(30);
          taskExecutor.setQueueCapacity(10);
          taskExecutor.setThreadNamePrefix("Executor-");
          taskExecutor.initialize();
          return taskExecutor;
      }
    }
  • 앞서 애플리케이션 개발에서의 Sync/Async가 애플리케이션 코드 관점이었다면, 이번엔 IO 처리 관점 (파일IO, 소켓IO 등...)

Socket IO의 발전과정

  • 멀티 프로세스 서버 - Process vs Socket = 1 vs 1
  • 멀티 쓰레드 서버 - Thread vs Socket = 1 vs 1
  • I/O 멀티플렉싱(multiplexing) 기법 도입 - Thread vs Socket = 1 vs n
    • select > poll > epoll/IOCP/Kqueue
  • https://jongmin92.github.io/2019/02/28/Java/java-with-non-blocking-io/
  • *"각 클라이언트 요청마다 별도의 스레드를 생성함으로써 프로세스를 생성하던 방법보다 리소스의 비용을 줄일 수 있었고, 스레드들이 서로 공유하는 메모리를 가질 수 있는 환경이 되었습니다. 그러나 I/O 멀티플렉싱(multiplexing) 기법을 사용한다면, 각 클라이언트 마다 별도의 스레드를 생성하는 것이 아닌 하나의 스레드에서 다수의 클라이언트에 연결된 소켓(파일 디스크립터)을 괸리하고 소켓에 이벤트(read/write)가 발생할 경우에만 별도의 스레드를 만들어 해당 이벤트를 처리하도록 구현할 수 있습니다."*
  • 즉, Socket I/O를 송수신하는 부분과 I/O 데이터를 활용해 로직을 처리하는 부분을 분리하는 것이 가능해졌다. IO 모델을 어떻게 설계해야 다수의 socket을 처리하는 가장 좋은 효율과 성능을 낼 수 있을까?

Sync/Async, Blocking/Non-Blocking 차이

  • Boost application performance using asynchronous I/O 문서Blocking-NonBlocking-Synchronous-Asynchronous 문서를 기반으로 설명

  • Blocking/NonBlocking은 I/O를 담당하는 함수를 호출했을 때 바로 리턴하느냐 마느냐가 관심사다.

  • Synchronous/Asynchronous는 I/O를 담당하는 함수의 작업 완료 여부를 누가 신경쓰냐가 관심사다.

  • Blocking/NonBlocking은 직관적으로 와닿는데, Synchronous/Asynchronous는 바로 이해되진 않는다

    • 호출되는 함수에게 callback을 전달해서, 호출되는 함수의 작업이 완료되면 호출되는 함수가 전달받은 callback을 실행하고, 호출하는 함수는 작업 완료 여부를 신경쓰지 않으면 Asynchronous다.
    • 호출하는 함수가 호출되는 함수의 작업 완료 후 리턴을 기다리거나, 또는 호출되는 함수로부터 바로 리턴 받더라도 작업 완료 여부를 호출하는 함수 스스로 계속 확인하며 신경쓰면 Synchronous다.
    • 아래 그림을 보면, Sync는 애플리케이션이 관심을 갖고 계속 확인하고 있는 반면, Async는 신경쓰지 않고 중간에 다른 일(other processing)을 하고 있다.
    • 웹에서 Polling(Sync와 개념적으로 비슷)과 Push(Async와 개념적으로 비슷)
      • Web Polling은 일정 주기로 서버에 변경사항이 생겼는지 주기적으로 체크하는 방식
      • Web Push는 서버에 변경사항이 발생할 경우 서버에서 클라이언트로 응답

4가지 구분

  • Blocking=Sync, Non-Blocking=Async가 아니다! 4가지는 다른 개념이다.
  • Sync/Blocking IO
    • Ex) 멀티 스레드 서버 (Thread vs Socket = 1 vs 1)
  • Sync/Non-Blocking IO
    • Ex) select(), epoll() 함수
    • Ex) future.isDone()
  • Async/Non-Blocking IO (AIO)
    • Ex) Window IOCP
  • Async/Blocking IO
    • 이와 같은 사례는 거의 없어 무시 가능
    • Ex) Node.js + MySQL 조합
    • "Blocking-Async는 별다른 장점이 없어서 일부러 사용할 필요는 없지만, NonBlocking-Async 방식을 쓰는데 그 과정 중에 하나라도 Blocking으로 동작하는 놈이 포함되어 있다면 의도하지 않게 Blocking-Async로 동작할 수 있다."

https://en.wikipedia.org/wiki/Asynchronous_I/O
https://homoefficio.github.io/2017/02/19/Blocking-NonBlocking-Synchronous-Asynchronous/

참고자료


Node.js vs Spring WebFlux

Node.js

  • 싱글 스레드 기반 비동기 IO 서버
    • (대충 풀어서 설명하면) 싱글 스레드인만큼 요청이 막 들어온다ㄱㄱ 중간에 오래걸리는 작업들(File, Network, DB 작업 등)은 워커로 보내 별도 스레드로 돌리고 다음 요청을 바로 이어 진행한다(비동기). 이벤트 루프는 계속 돌면서 완료된 작업은 이벤트 큐에서 콜백 함수를 하나씩 빼 실행한다.
  • https://sjh836.tistory.com/79
  • https://medium.com/@rpf5573/nodejs-event-loop-part-1-big-picture-7ed38f830f67
  • 키워드
    • 이벤트 루프, 이벤트 큐, 콜백 함수
    • V8 엔진, libuv

(Reactive) Spring WebFlux

  • vs Spring MVC
  • Spring MVC는 Servlet기반의 본질적으로 sync/blocking 방식이다. 따라서 스프링도 Reactive Programming을 지원하기 시작
  • 아직 Jdbc는 sync/blocking 방식으로 동작해서, 컨트롤러에서 비동기로 빠르게 받아도 뒷에서 DB작업 가면 성능 하락. 즉 Spring WebFlux를 통해 이제 스프링도 비동기를 지원하지만, 아직은 노드에 딸리는 현실. 따라서 앞쪽은 노드, 뒷쪽은 스프링으로 구성하기도. 나온지 얼마 안되었고 빠르게 성장하고 있다. R2DBC 등 나중에 스프링에서도 안정화되면 Reactive기반 개발이 활성화될듯함.
  • 노드와의 비교
    • node.js: single thread + event loop
    • spring webflux: worker thread default size는 서버의 core 개수로 설정 + event loop
    • CPU core 개수에 따라 node.js는 서버를 여러대(별도의 프로세스)를 동작시키는 방식으로 확장하고, Spring Webflux는 서버 한대(하나의 프로세스)에 여러 개의 worker thread를 생성하는 방식
  • RestTemplate vs WebClient
    • RestTemplate : Sync/Blocking
    • WebClient : Non-Blocking
    • 역시 점점 WebClient 사용 확대 추세
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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 27 28 29 30 31
글 보관함