본문 바로가기

Backend/Node.js

Single-Thread Server VS Multi-Thread Server

Single-Thread Event Loop Model, Node.js

  • JSP, Spring 등은 멀티스레드를 이용해서 requset와 response를 처리한다. 그리함으로서, 동시발생적인 사용자들을 잘 처리할 수 있기 때문이다.
  • 우리가 평소 사용하던 많은 웹 애플리케이션들은 멀티스레드기반이 더욱 친숙하다.
  • 하지만, Node.js는 싱글스레드 기반 이벤트 루프 구조를 선택했다.
    • 이벤트 루프 덕분에, 싱글스레드이지만 동시발생적인 사용자들을 잘 처리할 수 있게 된다.

Multi-Thread Request-Response Model(Synchronous)

Steps

  1. 클라이언트는 웹서버에 request를 보낸다.
    • 웹서버는 무한 루프를 돌면서 클라이언드의 리퀘스트를 기다리는 중이다.
  2. 웹서버는 내부적으로 제한된 스레드 풀을 유지하며 클라이언트의 request를 처리할 준비를 한다.
    • 웹서버는 내부적으로 하나의 클라이언트의 requset를 고르고, 스레드풀에서 스레드를 하나 선택한다. 그리고 그 스레드를 request에 할당한다.
  3. 스레드는 클라이언트의 request를 읽고, blocking I/O를 하거나 response를 준비한다.
  4. 스레드는 response를 웹서버에 보낸다.
  5. 웹서버는 response를 클라이언트에게 보낸다.
  • N명의 클라이언트에 대해서 이러한 처리를 각각 한다.
    • 즉, 1명의 클라이언트에 대해서 1개의 스레드가 할당된다.
  • 많은 클라이언트가 request를 요청한다면, 스레드들은 매우 바뻐지면서 클라이언트의 대기시간은 커진다
    • 스레드 풀의 갯수보다 더 많은 request가 들어온다면, 스레드가 할당되기까지 기다려야한다.
  • 또한, Blocking I/O로 인해 대기시간이 더 길어진다.
    • I/O호출이 발생하면 해당 스레드는 blocked상태이다.
  • Apache, Tomcat등의 웹 애플리케이션이 멀티스레드 requset-response모델이다.

Single-Thread Event Loop(Asynchronous)

  • Node.js는 멀티스래드 기반 모델보다 더 동시적으로(concurrently) 처리 할 수 있다.

step

  1. 클라이언트는 웹서버에 request를 보낸다.

  2. Node.js 웹서버는 request를 받아 Event Queue에 보낸다.

    • Node.js 웹서버는 또한 내부적으로 Event Loop라는 것이 존재한다. 무한 루프를 돌면서 request를 받는다.
    • Event Loop는 싱글 스레드를 이용한다. 이것이 Node.js의 핵심적인 처리 절차이다.
  3. Event Queue에 task(request)가 있다면,Event loop는 하나의 request를 선택해서 처리한다

    • I/O를 처리하고, 파일 요청이 끝나면 수행되는 callback 함수를 call stack에서 처리한다.
    • Event Loop는 그냥 메시지를 읽어서 Thread가 처리하는 것인지 아닌지를 따진다. 그냥 어디로 전달하는 지를 판단한다.
  4. 만약 request가 Blocking I/O를 요청하거나 complex한 computation task라면, 이러한 방식으로 진행된다.

    1. Internal Thread Pool에서 사용가능한 스레드를 선택한다. (event loop가 해당 request를 처리하지 않고 스레드가 처리한다.)
    2. 하나의 스레드를 선택하고, Client request를 처리한다.
    • I/O Blocking에 대해서는 thread pool에서 할당된다.
    • 해당 처리를 끝내면 이벤프 루프에게 보내고 이벤프 루프는 응답을 보낸다.(완료 한 내용을 callstack으로 보낸다..)
    • Non-blocking을 지원하지 않는 I/O가 있다면, 비동기적으로 처리하기 위해서 Thread pool에서 별도로 이용해서 처리한다.
  • 동시적으로 많이 들어오는 클라이언트의 request를 더 쉽게 처리할 수 있다.

  • 멀티스레드 기반 request- response모델보다 상대적으로 스레드가 덜 필요하다.

    • 결국, 시스템자원의 효율을 가져온다.
  • Node.js는 완전한 싱글스레드라고 하기에는 조금 어렵다.

  • 참고

(Rambabu Posa)[https://www.journaldev.com/7462/node-js-architecture-single-threaded-event-loop]

마이구미[https://mygumi.tistory.com/154] ( 위 링크의 번역 )

조대협님[https://meetup.toast.com/posts/89]