ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Node.js와 이벤트루프
    Programming/NodeJs 2022. 4. 4. 09:49

    •노드js는 C++로 작성된 자바스크립트 런타임(언어가 구동될 수 있는 환경)이며 내부에 V8 엔진과 libuv를 가지고 있다. 그래서 브라우저가 아닌 로컬에서 자바스크립트를 실행 가능/자바스크립트 런타임은 노드가 있다.

    *구성                                        Node.js
                     --------------------------------------------
                    Node.js core Library      |       Node.js Bindings
                     --------------------------------------------
                            V8 Engine                |                 libuv

    •싱글 스레드 논 블로킹 = 하나의 스레드로 동작하지만 I/O 발생시 비동기로 처리 가능 / 이는 이벤트 루프의 덕분으로 싱글 스레드로 여러 비동기 작업을 논블로킹으로 수행 할 수있다.

    •libuv는 C++로 작성된 노드가 사용하는 비동기 I/O 라이브러리이다. 이는 사실 운영체제의 커널을 추상화한 Wrapping 라이브러리로 커널이 어떤 비동기 API를 지원하는지 알고 있다.
             1)libuv에게 비동기 작업을 요청하면 커널이 지원하는지 확인하고 지원한다면 libuv가 대신 커널에게 비동기적으로 요청을 하고 응답

                 이 오면 우리에게 반환해주고, 요청한 작업을 커널이 지원하지 않는 다면 자신만의 워커 스레드가 담긴 스레드 풀을 사용한다.

     

             2)libuv는 기본 4개, uv_threadpool이라는 환경 변수로 최대 128개의 스레드를 가지는 스레드 풀을 생성 할 수 있다.

     

             ex)libuv가 스레드 풀에 파일 읽기를 요청하면 워커 스레드가 파일 시스템에게 동기 적으로 요청하고 응답을 받아 다시 스레드 

                  풀이 libuv에게 응답을 보내면 최종적으로 비동기로 노드js에게 응답을 보낸다.

    •싱글 스레드인 노드js가 논블로킹 작업을 통해서 비동기 작업을 지원할 수 있는 이유는 바로 자신의 메인 스레드를 사용하지 않고 libuv에게 작업을 위임하여 다른 스레드를 사용함으로써 논블로킹 I/O를 구현하고 그 기반에는 이벤트 루프가 있다.
     
    •이벤트 루프 구성: Timer Phase -> Pending Callbacks Phase -> Idle, Prepare Phase -> Poll Phase -> Check Phase -> Close Callbacks Phase (다음 단계로 넘어가는 걸 틱(Tick)이라고 한다.)

    •이벤트 루프가 노드의 비동기 실행을 도와주는 것과 별개로 싱글 스레드 이므로 한번에 하나의 페이즈에만 진입하여 한번에 큐에 담긴 하나의 작업만 수행 할 수 있다. 

    •노드js는 페이즈에 진입해  큐에 쌓인 작업을 처리, 처리 도중 이전 페이즈 작업의 콜백이나 스케줄링 등으로  새로운 작업이 큐에 추가되면 이를 처리하느라 다음 페이즈로 못넘어 갈 수 있다. 단, 페이즈는 시스템의 실행 한도의 영향을 받으므로 노드js가 한 페이즈에 영원히 갇히는 일은 없다. / 하지만 nextTickQueue는 시스템 실행 한도의 영향을 받지 않아 영원히 갇힐 수있다.

    •js파일을 노드로 실행하면 이벤트 루프를 생성하고 루프 바깥에서 .js 파일을 실행 한 뒤 실행이 끝나면 노드js는 이벤트 루프를 확인한다. 루프에 남은 작업이 있다면 노드는 이벤트루프에 진입하여 작업을 실행하고 없다면 process.on('exit',callback)을 실행하여 이벤트 루프를 종료한다. 

    ⭐️작업 순서 요약
    •이벤트 루프 생성 -> js파일 전부 읽음 -> 콜스택에 작업 쌓임->v8엔진은 비동기작업을 브라우저가 제공하는 webapis(예-timer web api등 )를 사용하여 실행 -> 그러면 콜스택에 적재된 비동기 작업은 WebAPIs를 통하여 실행된 콜백 함수가 콜백큐(이벤트 루프내 큐X)에 적재되고 -> 이벤트 루프는 콜스택의 동기(블로킹)작업이 완료되어  콜스택이 빌 때 까지 기다린 후 콜백 큐의 쌓인 함수를 확인한 뒤 -> 콜백 큐의 작업들이 이벤트 루프내 적절한 페이즈의 큐에 적재되어 libuv의 스레드풀의 워커 스레드에서 동기적으로 작업 처리 후 결과가-> 해당 페이즈로 콜백되고 완료된 결과물을 -> 콜스택으로 넘김 -> 실행

     

    *콜스택: 동기,비동기 작업 전부 대기 / 비동기는 webapis와 이벤트 루프를 통해 처리 후 콜백큐에서 콜스택으로 돌아옴 / 동기 작업은 콜스택에서 먼저 다 처리되고, 비동기 작업만 콜백 큐로 넘어간다.
    *콜백큐: 비동기로 실행되야 하는 콜백 함수가 보관되는 영역

    댓글

Designed by Kort.