alt
Home Node.js 디자인 패턴 1장 - 3. Reactor 패턴을 통한 Non-blocking 처리
Post
Cancel

Node.js 디자인 패턴 1장 - 3. Reactor 패턴을 통한 Non-blocking 처리

: 리소스(기다리고 있던 DB의 목적 리소스)에서 새 이벤트를 사용할 수 있을때까지 디멀티플렉서가 차단되다가, 처리된 다음 이벤트 큐로 전해지고, 이벤트 루프에 의해 핸들러가 호출되어 반응하는 것


이벤트 디멀티플렉싱

: Non-blocking 리소스를 처리하기 위한 기본적인 메커니즘

  • Disk I/O작업은 기본적으로 블로킹 I/O인데, 이걸 매번 block시키면 해당 스레드의 유휴시간이 길어지기 때문에 효율적으로 바꿔야 한다.

disk_io_blocking

  • 하나의 연결은 한 thread로 처리되는데, block이 많으면 위와같이 유휴시간이 길어진다.
  • 동시성을 위해서 각 연결 당 스레드 풀에서 스레드 가져와 할당해줄텐데, 이처럼 스레드 낭비(유휴시간)이 많다면 메모리를 소비하고 context switch를 유발하고, 낭비이다.
    • 따라서, 각 연결당 짧은 연결을 가지면서 context swtich를 유발하지 않는 것이 좋다.


Non-blocking으로 만드는 방법

  • Polling 방식: 매번 리소스를 받았는지 계속 확인하는 것은 Busy waiting이고, CPU를 계속 사용해야 해서 비효율적이다.
  • 동기 이벤트 디멀티플렉서: 감시중인 리소스들로부터 들어오는 I/O 이벤트이벤트 큐에 넣고, 처리할 새 이벤트 있을때까지 다시 차단


Reactor 패턴

: 각 I/O 작업과 관련된 핸들러를 갖는 것. Javascript의 Callback은 리액터 패턴의 핸들러를 구현한 것.

reactor_pattern

  • 이벤트가 생성되어 디멀티플렉서에 의해 이벤트 큐로 전해지고, 이벤트 루프에 의해 처리되는 즉시 각 핸들러는 호출된다.
  • 핸들러는 (5a)실행을 완료해 이벤트 루프에 제어를 반환할 수도, 혹은 새로운 비동기 요청(5b)이 발생해, 제어가 이벤트 루프로 돌아가기 전에디멀티플렉서에 새로운 이벤트를 등록(1)할 수도 있다.
  • 디멀티플렉서에 의해 처리 될 일이 없고, 이벤트 큐가 비어있게 되면 Node.js 어플리케이션은 끝난다.


libuv

: 운영체제마다 이벤트 디멀티플렉서를 위한 자체 인터페이스가 있으나, 불일치가 있을 수 있다. libuv라는 C 라이브러리를 통해 기본 시스템 호출을 추상화해, 문제를 해결

  • 또한, 해당 libuv는 Reactor 패턴을 구현하고 있어 이벤트 루프 생성, 이벤트 큐 관리 등에 대한 API를 제공한다.



Reference)

Node.js 디자인패턴

This post is licensed under CC BY 4.0 by the author.