Skip to content
Tags

Использование Node.js с Init и Monit

27/04/2010

Итак, я написал несколько забавных штучек на Node.js и хочу их запустить, к примеру, в локальной сети. Проблема здесь может быть в том, что Node, во первых, просто вылетает при ошибках (если 2001-й пользователь уронил скрипт, 2002-й уже не увидит сайта) и, во вторых, перезапускать её приходится руками — вводя что нибудь вроде node app.js 2> /var/log/node.log. Сегодня я этот процесс попробую автоматизировать.

Вообще к этой задаче можно подойти разными способами. Можно, например, ловить все исключения и показывать 500 страницу вместо вылета, как это делает Express. Но такой подход не спасёт нас от ошибок, переполнений и утечек памяти как в самой Node.js, так и в используемых библиотеках. Поэтому нам нужен способ отслеживать, жив ли наш сайт, и при необходимости его перезапускать.

Ещё одна проблема — Node.js обычно не запускают в виде демона. Можно конечно каждый раз дописывать & в конце строки вызова, но это опять же не очень удобно.

Init

Сперва нам надо сделать из Node демона. В Debian это удобнее всего реализовать с помощью init. Это, во первых, позволит запускать node.js фоновым процессом и, во вторых, даст нам удобные команды для запуска/завершения/управления демоном. Если Вы пользуетесь Debian Lenny, как я, init уже установлен. Если у Вас Убунту, Вам лучше посмотреть в сторону связки Upstart + Monit.

В Debian у нас уже есть шаблон файла настройки init — он лежит в /etc/init.d/skeleton. Копируем его, переименовываем в nodejs и редактируем:

  cp /etc/init.d/skeleton /etc/init.d/nodejs
  vim /etc/init.d/nodejs
  

В нём меняем название и описание сервиса, запускаемое приложение и опции, путь к node:

DESC="Node.js-based service"
NAME=node
DAEMON=/usr/local/bin/$NAME
  

Кстати, узнать откуда именно запускается у Вас node.js можно командой which node. Здесь же в переменную DAEMON_ARGS можно прописать JS-файл, который Node будет запускать по умолчанию.

Ниже будет функция do_start(), которая собственно и отвечает за запуск демона. Там можно изменить команду, которая запускает сам демон. Я, например, добавил перенаправление ошибок в лог:

  start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
  || return 1
  start-stop-daemon --start --quiet --pidfile $PIDFILE -b -m --exec $DAEMON -- \
  $DAEMON_ARGS 2> /var/log/$NAME.log \
  || return 2
  

Для Node.js надо добавить опции -b и -m, т.к. самостоятельно Node не станет демоном. Здесь же можно добавить дополнительные команды при запуске сайта — например, удаление временных файлов или запуск сервера баз данных.

Ниже есть функция do_stop. Код, останавливающий сервер, в принципе и без изменений сработает неплохо, но если при остановке демона надо выполнить какие-либо действия, они идут как раз сюда.

Теперь сохраняем получившийся файл. Надо дать ему разрешение на выполнение:

  chmod +x /etc/init.d/nodejs
  

Попробуем запустить демон (я использую в качестве параметра запуск поискового сайта):

  /etc/init.d/nodejs start
  ps ax | grep node
  /etc/init.d/nodejs stop
  

Если всё прошло нормально, после команды start наш демон должен появиться в списке процессов, а после stop — исчезнуть.

Monit

Итак, демон у нас готов. Теперь нам нужен Monit. Ставим его:

  apt-get install monit
  

По сути, Monit штука довольно простая. Он периодически проверяет жив ли определённый сервис, и выполняет действия в зависимости от ответа.

Прежде чем его запускать, надо его настроить. Редактируем /etc/monit/monitrc. Там есть много примеров, наш код будет выглядеть примерно так:

set logfile /var/log/monit.log

check host nodejs with address 192.168.172.128
    start program = "/etc/init.d/nodejs start"
    stop program  = "/etc/init.d/nodejs stop"
    if failed port 8000 protocol HTTP
        request /
        with timeout 10 seconds
        then restart
  

Если вы знаете английский, конфиг читается довольно легко. Нам надо только указать правильные адрес и порт, которые будет проверять Monit (именно те, на которых висит наш сайт), и добавить что в случае недоступности в течении 10 секунд его надо перезапустить.

Здесь есть одна особенность. Monit запускает указанные команды в «чистом» окружении — т.е. из переменных окружения там доступна только PATH. Для работы Node нам нужна ещё переменная HOME, поэтому добавляем её в /etc/init.d/nodejs:

DESC="Node.js-based service"
NAME=node
DAEMON=/usr/local/bin/$NAME
export HOME=/root
  

Вам надо сначала проверить, чему равна HOME в вашем случае с помощью команды set. Теперь запускаем сам Monit:

  monit -d 60 -c /etc/monit/monitrc
  

Флаг -d 60 говорит о том что наше приложение надо проверять каждые 60 секунд, -c указывает какой файл настроек использовать. Теперь, если наш сайт на node.js внезапно упадёт, Monit+init оперативно вернут его к жизни. Параллельно Monit может наблюдать и другие приложения: CouchDB, MongoDB, поисковый сервер Sphinx — всё, что может понадобиться для сайта.

Ссылки по теме

Реклама
11 комментариев
  1. Kolyaj permalink

    >> Node, во первых, просто вылетает при ошибках
    Событие uncaughtException же

  2. Akzhan permalink

    Вам стоит прочесть http://habrahabr.ru/blogs/sysadm/83775/

  3. Антон permalink

    Наверно я неправильно понимаю архитектуру самого NodeJS, а также принципы построения решения на нем, и поэтому возник вопрос: тут принцип другой, нежели, например у nginx/apache/mysql, у которых есть хост-процесс, создающий дочерние потоки (процессы?) для параллельной обработки поступающих запросов?
    Просто в данной статье намека на это дело не увидел, вот и хотелось бы уточнить))

    • Вкратце: старт виртуальной машины V8 — дело затратное. Если делать это для каждого запроса, будет медленнее. Кстати, nginx запускает несколько воркеров, каждый из которых обрабатывает много поступающих запросов. В ноде тоже применяется похожий паттерн — в частности, с общим файловым дескриптором.

      Суть статьи в том что если скрипт в Node.js падает, его должен кто то поднять. Даже если у нас есть мастер-поток и дочерние, кто то всё равно должен подстраховывать мастер-поток от неожиданностей. И для непрерывной работы и Nginx, и Apache, и MySQL в Debian обычно запускаются через описанный механизм — Init + Monit.

Trackbacks & Pingbacks

  1. Использование с Init + Monit « nodeJS
  2. Tweets that mention Использование Node.js с Init и Monit « Механический мир -- Topsy.com
  3. Что такое «асинхронная событийная модель», и почему сейчас она «в моде» « Домик Миа

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: