Node.js: Погружение в цикл событий

Node.js является событийно-ориентированной системой. Другими словами, все, что происходит в ноде, является реакцией на события и события вызывают каскад колбеков. Этот механизм работает на основе библиотеки libuv и называется циклом событий (event loop).

node.js

 

Есть популярное мнение, что цикл событий является одним из самых «недопонимаемых» принципов платформы (Node.js).

Общие заблуждения

Как я уже упоминал, в цикл событий Node.js построен на базе библиотеки libuv. В одном из своих выступлений, Bert Belder, один из разработчиков libuv, при помощи поиска картинок известной поисковой системы, показал, на сколько разные подходы используют люди для того, чтобы изобразить своё понимание (далеко не всегда правильное) механизмов работы цикла событий.Node.js event loop

Рассмотрим самые популярные заблуждения.

Заблуждение 1: Цикл событий работает в отдельном потоке

Заблуждение

Существует главный поток, исполняющий пользовательский javascript код и существует другой поток, в котором работает цикл событий. Каждый раз, когда выполняется асинхронная операция, главный поток передает управление в поток цикла событий, а по завершению операции, цикл событий передает сообщение о необходимости выполнить колбек в главный поток.

Реальность

Существует только один поток, который выполняет пользовательский код javascript и цикл событий. Выполнение колбеков (весь пользовательский код, по сути, является колбеком) инициируется циклом событий. Ниже затронем этот вопрос чуть подробнее.

Заблуждение 2: Вся асинхронная работа выполняется пулом потоков

Заблуждение

Асинхронные операции, такие как работа с фаловой системой, осуществление исходящих HTTP-запросов или запросы к базам данных, всегда выполняются в пуле потоков, контролируемых библиотекой libuv.

Реальность

Действительно, по умолчанию, libuv создает пул, состоящий из четырех потоков, которым могут обрабатываться асинхронные вызовы. Но современные операционные системы предоставляют асинхронные интерфейсы для большинства задач ввода-вывода, например AOI в Linux. Там, где это возможно, libuv использует доступные асинхронные интерфейсы, избегая использования пула потоков. Похожая ситуация сложилась и с различным сторонним софтом, например базами данных. В данном случае, авторы драйверов используют асинхронные интерфейсы охотнее, чем пулы потоков. В общем, пулы потоков используются для асинхронных взаимодействий только в самых крайних случаях.

Заблуждение 3: Цикл событий — это что-то вроде стека или очереди

Заблуждение

Цикл событий содержит FIFO очередь из асинхронных заданий и, по завершению задания, вызывает его колбек.

Реальность

Цикл событий содержит структуры, похожие на очереди, но он не обрабатывает весь стек последовательно. Цикл событий представляет собой процесс, состоящий из этапов (групп задач), которые выполняются по очереди.

Подробнее про этапы цикла событий

Для полного понимания цикла событий, мы должны понять, какие задачи выполняются на каком этапе.  В графическом виде работу цикла событий можно представить так:node.js event loop phases

Рассмотрим этапы чуть подробнее. Полное описание можно найти на официальном сайте.

Timers

На данном этапе выполняется код, инициированный через setTimeout() или setInterval().

IO Callbacks

Здесь выполняются почти все колбеки. Как было сказано ранее, почти весь код в Node.js — колбеки (например входящий http запрос вызывает каскад колбеков), а значит, почти весь пользовательский код выполняется на этом этапе.

IO Polling

Опрос новых событий, которые будут обработаны в следующем проходе цикла.

Set Immediate

Выполняет функции, зарегистрированные через setImmediate().

Close

На данном этапе выполняются все колбеки для событий on(‘close’).

Мониторинг цикла событий

Мы значем, что все в node.js приложении выполняется через цикл событий. А значит, если мы сможем собрать его мертирики, мы сможем достоверно знать общее состояние и производительность приложения.

К сожалению, нет единого API для получения метрик цикла событий, поэтому каждая утилита представляет свой набор метрик. Давайте подумаем, что мы можем получить.

Частота тиков

Количество тиков в единицу времени.

Длительность тика

Время выполнения одного тика.

Дальнейшие результаты получены при помощи нативного модуля мониторинга от Dynatrace.

Метрики частоты и длительности тика в действии

На первый взгляд, результаты тестирования могут быть очень даже удивительными.

В следующем сценарии, использовано приложение на express.js, которое осуществляет вызов на другой http сервер.

Четыре сценария тестирования:

1. Простой

Нет входящих запросов.

2. ab -c 5

5 конкурентных запросов одновременно

3. ab -c 10

10 конкурентных запросов одновременно

4. ab -c 10 (намеренная задержка ответа)

Http сервер возвращает ответ через с задержкой в 1 секунду. Такое поведение должно вызвать накопление очереди запросов, ожидающих ответа.

node.js event loop tick frequency

На графике мы можем видеть интересные результаты: частота и длительность тиков цикла событий динамически подстраивается под выполняемые операции.

Если приложение простаивает, то есть в очереди нет ожидающих выполнения задач (таймеров колбеков и так далее),  цикл событий начинает работать на минимальной частоте, в ожидании входящих событий.

Также мы видим, что метрики под одной и тоже входящей нагрузкой не одинаковы, цикл событий адаптирует частоту тиков к реальной нагрузке.

Судя по всему, лучшая производительность приложения достигается на 5 одновременных подключениях.

Не смотря на всю информативность этих данных, мы по прежнему не можем знать, какой этап занял сколько времени в каждом тике.  Добавим еще пару значений для мониторинга.

Задержки обработки

Это значение показывает, как долго асинхронная задача ожидала выполнения пулом потоков.

Высокое значение этой метрики говорит о занятости или полном заполнении пула потоков.

Для наглядности, можно использовать приложение, обрабатывающее изображения при помощи модуля Sharp. Обработка изображений — довольно сложная операция и Sharp будет использовать пул потоков.

node.js work processed latency

Запустив снова утилиту Apache bench с пятью одновременными подключениями, можно увидеть, что время ожидания обработки вырастает практически с нуля до 8-10 мс в среднем и превышает 20 мс в пиках.

Задержки цикла событий

Данная метрика отражает время задержки выполнения задачи, созданной при помощи setTimeout().

Высокое значение этой метрики означает, что цикл событий занят обработкой колбеков.

Для демонстрации, можно использовать приложение, вычисляющее числа Фибоначчи не самым оптимальным способом.node.js event loop latencyПри помощи все той же утилиты ab и пяти одновременных подключений, можно увидеть, что из-за заполнения очереди обработки колбеков, значительно вырастает время задержки цикла событий.

Все четыре метрики позволяют лучше понять, как работает node.js под капотом.

Настройка цикла событий

Конечно, метрики, сами по себе, не помогут решить проблему производительности приложения. Нужны конкретные действия, основанные на знании значений метрик. Несколько советов, что делать, когда цикл событий кажется перегруженным.

node.js tuning the event loop

Использование всех доступных ядер CPU

Приложение Node.js выполняется в одном потоке. В условиях современных многоядерных процессоров, это означает, что нагрузка не распределяется на все доступные ядра и они простаивают.Использование модуля cluster позволяет node легко создавать дочерние процессы на каждое доступное ядро. Каждый дочерний процесс имеет свой цикл событий и родительский процесс прозрачно распределяет нагрузку между всеми дочерними процессами.

Настройка пула потоков

Как уже говорилось выше, libuv создает пул из 4 потоков. Значение по умолчанию может быть переопределено переменной окружения UV_THREADPOOL_SIZE.

С одной стороны, увеличение пула может помочь решить проблему при работе с вводом-выводом, с другой стороны, это приведет к большему расходу оперативной памяти и/или процессорного времени. Рекомендую подходить к этой настройке с осторожностью.

Делегирование специфических задач

Если Node.js покажется вам не самой подходящей платформой для определенного рода вычислений, можно просто вынести конкретный блок задач в отдельный сервис, написанный на более подходящем языке.

Подведем итоги

  • Цикл событий — это основа приложения Node.js.
  • Его работа часто недопонимается — на самом деле, это набор этапов, на каждом из которых выполняются задачи разных видов.
  • На данный момент нет встроенного механизма получения метрик цикла событий, но есть много различных сторонних решений.
  • Метрики могут помочь понять, где находятся узкие для производительности места.

Yii2: Современный стиль PHP кода

 

Keep calm and follow PHP PSR

При разработке приложений на Yii 2 полезно придерживаться стиля кода его разработчиков. Если, конечно, у вас нет своего устоявшегося стиля, соответствующего современному PHP и PSR. Читать далее Yii2: Современный стиль PHP кода

Yii2: Обработка ошибок

 

Обработка ошибок в Yii 2

Обработчик ошибок включен в Yii 2 по умолчанию. Отключить его можно добавив следующий код в стартовый скрипт приложения web/index.php:

Конфигурация по умолчанию

В шаблонах приложений Yii 2 basic и advanced обработчик ошибок подключен как компонент приложения errorHandler. Рассмотрим примеры конфигурации:

  • приложение basic: config/web.php;
  • приложение advanced: индивидуальные настройки для каждого из приложений frontend/config/main.php и backend/config/main.php.

Читать далее Yii2: Обработка ошибок

PHP PDO — работаем с базами данных правильно

PHP PDO Основы

Термин PDO является сокращением понятия PHP Data Objects. Как можно судить по названию, эта технология позволяет работать с содержимым базы данных через объекты. Читать далее PHP PDO — работаем с базами данных правильно

Обновление ICU на CentOS/Red Hat/Fedora

yii2 formatter icu

Столкнулся с проблемой, при выводе времени, yii\i18n\Formatter формирует для зоны 'Europe/Moscow' время, соответствующее GMT+4:

выводил :

В конфиге приложения временная зона указана явно: 'timeZone' => 'Asia/Omsk'. Читать далее Обновление ICU на CentOS/Red Hat/Fedora

Yii2: Разбираемся с сессиями

yii2 session flash

Использование сессий — это хороший способ сохранять информацию между визитами пользователя на сайт. Изначально, в php, работа с сессиями ведется через глобальный массив $_SESSION. Для удобства работы, экземпляр приложения yii2 содержит компонент yii\web\Session, доступный через Yii::$app->session.

Открытие и закрытие сессий

Простой код, иллюстрирующий работу с сессиями.

Читать далее Yii2: Разбираемся с сессиями

Yii2: Выпадающий список DropDownList

Yii2: Выпадающий список DropDownListПри создании пользовательских интерфейсов, кроме текстовых полей, часто используются выпадающие списки — Drop-Down List. Этот элемент позволяет ограничить пользователя выбором одного или нескольких вариантов из предложенного списка.

Виджет yii\widgets\ActiveField  уже содержит метод dropDownList( $items, $options = [] ) , являющийся оберткой для yii\helpers\BaseHtml::activeDropDownList( $model, $attribute, $items, $options = [] )  отрисовывающего выпадающий список, используя html тег select . Читать далее Yii2: Выпадающий список DropDownList

Yii2: поля ActiveForm

Yii2: поля ActiveFormНаверняка, одними из самых часто используемых вами yii2 виджетов станут yii\widgets\ActiveForm и его улучшенная Bootstrap 3 версия — yii\bootstrap\ActiveForm.

Сегодня рассмотрим использование yii\bootstrap\ActiveForm  в деталях. Наглядным примером послужит демонстрация и исходные коды (модуль simpleactiveform). Читать далее Yii2: поля ActiveForm

Yii2: Разбираемся с GridView

Картинка в gridview yii2

Специально для данной заметки, я подготовил пример использованием разных параметров GridView. Исходники модуля и всего приложения, доступны на битбакете.

За основу взять код, полученный при помощи генератора Gii. Типичный код GridView после автоматической генерации:

Читать далее Yii2: Разбираемся с GridView

Добавляем свободное место с lvm на CentOS

Добавляем свободное место с lvm на CentOSВ моем случае, добавить свободное место понадобилось на виртуальной машине с asterisk под hyper-v. Средствами hyper-v можно легко увеличить размер виртуального жесткого диска, но в lvm linux место само собой не добавится. Оставлю здесь простую инструкцию, как увеличить количество свободного места. Может кому еще пригодится.

Обстановка

Размер виртуального диска — 10 Гб. А linux видит только 4. Читать далее Добавляем свободное место с lvm на CentOS

Yii2: Вникаем в Pjax

regular request vs pjax requestПопулярный ныне js фреймворк jQuery оброс большим количеством разнообразных плагинов. Одним из таких плагинов является pjax, позволяющий легко создавать веб приложения с использованием связки ajax и pushState. Эта технология позволяет после нажатия ссылки или submit на форме, отправить на сервер специальный запрос и получить в ответ только то содержимое, которое необходимо обновить на странице, затем pjax заменяет старое содержимое новым и добавляет в историю браузера и адресную строку актуальную url ссылку, без обновления всей страницы. Читать далее Yii2: Вникаем в Pjax

Yii2: Простое приложение c AngularJS фронтендом. Клиентская часть 2

На данный момент мы имеем готовое RESTful api приложение в серверной части и простое AngularJS приложение в клиентской части. Дело за малым, обеспечить связь второго с данными из первого.

Доработаем главный модуль app.js

Добавим описание модуля, обеспечивающего работу с данными о фильмах, yii2AngApp.film:

Читать далее Yii2: Простое приложение c AngularJS фронтендом. Клиентская часть 2

Yii2: Простое приложение c AngularJS фронтендом. Клиентская часть 1

Ну что же, серверная часть готова, самое время взяться за клиентскую.

Пользовательский интерфейс мы создадим используя js фреймворк angelarjs (функционал) и css фреймворк twitter bootstrap (интерфейс).

Одностраничное приложение

Вся работа с клиентской частью приложения будет осуществляться через уже созданный нами файл client/index.html, который нам и отдает веб-сервер при открытии http://client.local.

Описание приложения AngularJS

Добавим атрибут  ng-app тегу  html. Назовем наше приложение yii2AngApp.

Читать далее Yii2: Простое приложение c AngularJS фронтендом. Клиентская часть 1

Yii2: Простое приложение c AngularJS фронтендом. Серверная часть

Теперь, когда все подготовительные работы закончены, можно всерьез заняться нашим приложением. PHP фреймворк Yii 2.0 позволяет быстро и просто создать необходимый нам функционал, включая RESTful api.

Забыл сказать, в этом учебном приложении мы реализуем простой каталог фильмов. Данные каталога будем хранить в базе данных mysql.

Структура базы данных

Создадим базу данных yii2-ang и добавим в нее таблицу film со следующей структурой:

  • id — int(11)
  • title — varchar(255)
  • storyline — text
  • director — varchar(100)
  • year — int(4)

Читать далее Yii2: Простое приложение c AngularJS фронтендом. Серверная часть

Yii2: Простое приложение c AngularJS фронтендом. Подготовка

Для начала, подготовим рабочее окружение, скачаем все необходимые библиотеки и создадим шаблоны будущих приложений. Будем считать, что у нас есть 2 домена: client.local и server.local. Создадим для них корневые соответствующие корневые каталоги: client и server. И настроим наш веб-сервер. Примерная конфигурации для apache:

В дальнейшем будем работать с этими каталогами по отдельности. Читать далее Yii2: Простое приложение c AngularJS фронтендом. Подготовка

Yii2: Простое приложение c AngularJS фронтендом. Введение

angularjs yii2В далекие времена веб 1.0 одностраничные веб-приложения (Single Page Application) были как мамонты: редкие и, зачастую, построенные на костылях с большим количеством разной степени структурированности js кода.

В наше время 2.0 существуют и успешно развиваются не только серверные, но и клиентские фреймворки и библиотеки: JQuery, Backbone.jsEmber.jsCanJSAngularJSKnockoutJS.

По сути, разделение приложения на серверную и клиентскую части, в большинстве случаев оправдывается снижением нагрузки на сервер и упрощением поддержки большего количества клиентских платформ.

В нескольких статьях, постараемся разобраться, как за несколько минут создать простое одностраничное приложение, используя AngularJs и Yii Framework 2.0. Читать далее Yii2: Простое приложение c AngularJS фронтендом. Введение

Запись открытой лекции по Yii 2

Запись открытой лекции по Yii 2

Открытую лекцию провел Павел Климов, один из четырех основных разработчиков фреймворка yii2.

За сорок минут Павел подробно и, в тоже время, просто рассказал о структуре приложения, архитектуре mvc в Yii 2.0, об управлении asset‘ами, Active Record‘е, обработке событий и поведениях, а так же, о стандартных расширениях yii2.

Видео будет полезно всем начинающим и не очень программистам.

Читать далее Запись открытой лекции по Yii 2

Таблица символов ASCII

Таблица asciiНабор символов ASCII (American standard code for information interchange) — таблица, в которой некоторым символам сопоставлены определенные машинные коды. Данная таблица была стандартизирована в 1963 в США. Американцы, чаще всего, произносят название как эски, а европейцы и русские предпочитают говорить аски.

Символы в таблице хранятся в виде семи-битного числа, соответственно, изначальный размер таблицы составлял 128 символов. В связи с тем, что современные компьютеры, оперируют восьми-битными байтами, таблица позже была расширена до 256 символов и стала включать национальные символы. Читать далее Таблица символов ASCII

Yii2: релиз 2.0.3 по расписанию

Yii 2.0.3 release новый релизКак по часам, вышел очередной стабильный релиз замечательного php-фреймворка Yii 2.

Версия 2.0.3 является патч-релизом и содержит около 50 улучшений и исправлений ошибок. Полный перечень изменений можно найти здесь. По доброй традиции, над улучшениями и исправления трудилось большое количество участников сообщества.

Отдельно хочу отметить, что документация не отстает от самого фреймворка и активно дописывается и переводится на большое количество языков.

Поддержать проект можно присоединившись к сообществу:

Рассмотрим некоторые из улучшений в этом релизе. Читать далее Yii2: релиз 2.0.3 по расписанию

Yii2: защита текстов блога от копипаста

yii2 защита от копипаста copy-pasteГлобальная сеть призвана нести информацию в массы. Но на данном этапе развития сети Интернет, количество сайтов, содержащих материалы других авторов, со ссылкой на автора и оригинал или без нее, многократно превышает количество сайтов с уникальными авторскими статьями, описанием собственных разработок и другими полезными материалами. А все потому, что копипаст чужих материалов может приносить не маленький доход, при должном подходе. Читать далее Yii2: защита текстов блога от копипаста

Советы и трюки по работе с linux, web и многое другое. Только уникальные материалы!