Увидел свет стабильный релиз платформы node.js 0.8, предназначенной для обеспечения выполнения высокопроизводительных сетевых приложений на языке JavaScript. Платформа может быть использована как для серверного сопровождения работы Web-приложений, так и для создания обычных клиентских и серверных сетевых программ. Для расширения функциональности приложений для Node.js подготовлена большая коллекция модулей, в которой можно найти модули с реализацией серверов и клиентов HTTP, SMTP, XMPP, DNS, FTP, IMAP, POP3, модули для интеграции с различными web-фреймворками, обработчики WebSocket и Ajax, коннекторы к СУБД (MySQL, PostgreSQL, SQLite, MongoDB), шаблонизаторы, CSS-движки, реализации криптоалгоритмов и систем авторизации (OAuth), XML-парсеры.
Для обеспечения обработки большого числа параллельных запросов node.js задействует асинхронную модель запуска кода, основанную на обработке событий в неблокирующем режиме и определении callback-обработчиков. В качестве способов мультиплексирования соединений поддерживаются такие методы, как epoll, kqueue, /dev/poll и select. Для мультиплексирования соединений используется библиотека libuv, которая является надстройкой над libev в системах Unix и над IOCP в Windows. Для создания пула потоков (thread pool) задействована библиотека libeio, для выполнения DNS-запросов в неблокирующем режиме интегрирован c-ares. Все системные вызовы, вызывающие блокирование, выполняются внутри пула потоков и затем, как и обработчики сигналов, передают результат своей работы обратно через неименованный канал (pipe). Выполнение JavaScript-кода обеспечивается через задействование разработанного компанией Google движка V8.
По своей сути node.js похож на фреймворки Perl AnyEvent, Ruby Event Machine и Python Twisted, но цикл обработки событий (event loop) в Node.js скрыт от разработчика и напоминает обработку событий в web-приложении, работающем в браузере. При написании приложений для node.js необходимо учитывать специфику событийно-ориентированного программирования, например, вместо выполнения "var result = db.query("select..");" с ожиданием завершения работы и последующей обработкой результатов, в Node.js использует принцип асинхронного выполнения, т.е. код трансформируется в "db.query("select..", function (result) {обработка результата});", при котором управление мгновенно перейдёт к дальнейшему коду, а результат запроса будет обработан по мере поступления данных. Ни одна функция в Node.js не должна напрямую выполнять операции ввода/вывода - для получения данных с диска, от другого процесса или из сети требуется установка callback-обработчика.
Ключевые новшества Node.js 0.8:
- Внесение нескольких ключевых улучшений в новые версии V8 и libuv привело к существенному увеличению пропускной способности при выполнении операций записи и чтения данных. Если сравнивать с версией 0.6.19, то для буфера 1024 скорость записи потока через io.js увеличилась с 19 до 61 Мб/сек, 4096 - c 59 до 109 Мб/сек, 16384 - c 83 до 182 Мб/сек, 65536 - c 97 до 181 Мб/сек. Скорость чтения при этом возросла в полтора - два раза. При тестировании производительности скорости обработки запросов производительность простейшего сетевого приложения увеличилась с 3317 до 3795 запросов в секунду при размере сообщения 123 байт и с 218 до 749 для больших сообщений, размером 123456 байт. Большое увеличение производительности также наблюдается при выполнении JavaScript кода новой версией движка V8 (3.11.10.10);
- Осуществлён переход на новую систему сборки. Вместо написанной на языке Python системы сборки WAF теперь используется GYP, применяемый для сборки проекта Chrome/Chromium. Отличительной чертой GYP является генерация родных для каждой платформы сборочных сценариев (Makefiles для Unix, Visual Studio для Windows и XCode для Mac OS X). Кроме улучшения поддержки сборки для различных платформ GYP позволяет обеспечить интеграцию с процессом сборки движка V8 и улучшить управляемость проектом;
- Переход от непосредственного использования библиотек libev и libeio к использованию прослойки libuv позволило унифицировать поддержку платформ Unix и Windows, но привело к некоторому изменению API, специфичному для определённых платформ. Поэтому, при переходе на версию 0.8 возможно потребуется небольшая переработка кода. Например, прекращена поддержка прямого вызова ev_* и eio_*, объявлен устаревшим http.Client(), path.{exists,existsSync} заменены на fs.{exists,existsSync}, а tty.setRawMode(mode) на tty.ReadStream#setRawMode();
- Возвращена поддержка работы с файловыми дескрипторами. В версии 0.6 была прекращена поддержка метода listenFD и массива customFds, так как была признана некроссплатформенной и специфичной для Unix. В итоге многие пользователи выразили своё возмущение и отказались от перехода на 0.6. В версии 0.8 разработчики признали свою ошибку и вернули функциональность прямой работы с файловыми дескрипторами - server.listen({ fd: number }), а также добавили в stdio возможность передачи открытых дескрипторов дочерним процессам через child_process.spawn();
- Полностью переработан модуль cluster, предназначенный для организации работы кластера из нескольких процессов node.js. API в целом остался обратно совместимым, но внесены и некоторые нарушающие совместимость изменения.
- Добавлен экспериментальный модуль domain, позволяющий связать несколько разных операций ввода/вывода и выполнить их обработку в виде единой группы.
- Проведена чистка и рефакторинг модулей Repl, Readline и TTY с целью повышения удобства разработки;
- В модуль fs добавлены методы fs.appendFile() и fs.appendFileSync(), а также поддержка режимов "wx", "wx+", "ax" и "ax+" для fs.open() и fs.openSync().