node.js

Web service 2012.02.09 16:31

 

node.js 사용만 하다가. node.js 내부에 대한 궁금증이 생겼다..

V8 + thread pool + event loop 가 핵심이다.

 

node.js 의 소스디렉토리 : https://github.com/joyent/node/

 

https://developer.palm.com/index.php?id=2109&option=com_content&view=article 에 따르면, Hp webOS 2.1에 탑재(built-in)되어 있다.

image

아키텍처는 다음과 같다. (http://blog.zenika.com/index.php?post/2011/04/10/NodeJS)

image

 

중요 라이브러리는 2가지가 있다.

1. C event loop 라이브러리 (libev) : libev - a high performance full-featured event loop written in C
(http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod)

* 이 라이브러리의 주요 특징은 Timer(ev_timer), FD(ev_io), 시그널(ev_signal), 상태(ev_stat)이 있다.

// a single header file is required
  #include <ev.h>

  #include <stdio.h> // for puts

  // every watcher type has its own typedef'd struct
  // with the name ev_TYPE
  ev_io stdin_watcher;
  ev_timer timeout_watcher;

  // all watcher callbacks have a similar signature
  // this callback is called when data is readable on stdin
  static void
  stdin_cb (EV_P_ ev_io *w, int revents)
  {
    puts ("stdin ready");
    // for one-shot events, one must manually stop the watcher
    // with its corresponding stop function.
    ev_io_stop (EV_A_ w);

    // this causes all nested ev_run's to stop iterating
    ev_break (EV_A_ EVBREAK_ALL);
  }

  // another callback, this time for a time-out
  static void
  timeout_cb (EV_P_ ev_timer *w, int revents)
  {
    puts ("timeout");
    // this causes the innermost ev_run to stop iterating
    ev_break (EV_A_ EVBREAK_ONE);
  }

  int
  main (void)
  {
    // use the default event loop unless you have special needs
    struct ev_loop *loop = EV_DEFAULT;

    // initialise an io watcher, then start it
    // this one will watch for stdin to become readable
    ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ);
    ev_io_start (loop, &stdin_watcher);

    // initialise a timer watcher, then start it
    // simple non-repeating 5.5 second timeout
    ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.);
    ev_timer_start (loop, &timeout_watcher);

    // now wait for events to arrive
    ev_run (loop, 0);

    // break was called, so exit
    return 0;
  }

 

소개 자료는 다음과 같다.

Libev is an event loop: you register interest in certain events (such as a file descriptor being readable or a timeout occurring), and it will manage these event sources and provide your program with events.

To do this, it must take more or less complete control over your process (or thread) by executing the event loop handler, and will then communicate events via a callback mechanism.

You register interest in certain events by registering so-called event watchers, which are relatively small C structures you initialise with the details of the event, and then hand it over to libev by starting the watcher.

 

Libev supports select, poll, the Linux-specific epoll, the BSD-specific kqueue and the Solaris-specific event port mechanisms for file descriptor events (ev_io), the Linux inotify interface (for ev_stat), Linux eventfd/signalfd (for faster and cleaner inter-thread wakeup (ev_async)/signal handling (ev_signal)) relative timers (ev_timer), absolute timers with customised rescheduling (ev_periodic), synchronous signals (ev_signal), process status change events (ev_child), and event watchers dealing with the event loop mechanism itself (ev_idle, ev_embed, ev_prepare and ev_check watchers) as well as file watchers (ev_stat) and even limited support for fork events (ev_fork).

It also is quite fast (see this benchmark comparing it to libevent for example).


2. c thread pool 라이브러리 (liibeio)

http://pod.tst.eu/http://cvs.schmorp.de/libeio/eio.pod

* async 기능 제공

예제 파일

static struct ev_loop *loop;
static ev_idle repeat_watcher;
static ev_async ready_watcher;

/* idle watcher callback, only used when eio_poll */
/* didn't handle all results in one call */
static void
repeat (EV_P_ ev_idle *w, int revents)
{
  if (eio_poll () != -1)
    ev_idle_stop (EV_A_ w);
}

/* eio has some results, process them */
static void
ready (EV_P_ ev_async *w, int revents)
{
  if (eio_poll () == -1)
    ev_idle_start (EV_A_ &repeat_watcher);
}

/* wake up the event loop */
static void
want_poll (void)
{
  ev_async_send (loop, &ready_watcher)
}

void
my_init_eio ()
{
  loop = EV_DEFAULT;

  ev_idle_init (&repeat_watcher, repeat);
  ev_async_init (&ready_watcher, ready);
  ev_async_start (loop &watcher);

  eio_init (want_poll, 0);
}

특징

This library provides fully asynchronous versions of most POSIX functions dealing with I/O. Unlike most asynchronous libraries, this not only includes read and write, but also open, stat, unlink and similar functions, as well as less rarely ones such as mknod, futime or readlink.

It also offers wrappers around sendfile (Solaris, Linux, HP-UX and FreeBSD, with emulation on other platforms) and readahead (Linux, with emulation elsewhere>).

The goal is to enable you to write fully non-blocking programs. For example, in a game server, you would not want to freeze for a few seconds just because the server is running a backup and you happen to call readdir.

 

 

3. V8 (구글 작품)

http://code.google.com/p/v8/

http://code.google.com/intl/ko-KR/apis/v8/embed.html

Posted by 김용환 '김용환'