Рекомендации и руководство по устранению неполадок в приложениях Node.js в Службе приложений Azure (Windows)

В этой статье описываются рекомендации и способы устранения неполадок приложений Node.js для Windows, запущенных в службе приложений Azure (с помощью iisnode).

Предупреждение

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

Конфигурация IISNODE

В этом файле схемы показаны все параметры, которые вы можете настроить для iisnode. Ниже приведены параметры, которые полезны для вашего приложения:

nodeProcessCountPerApplication

Этот параметр определяет количество процессов Node, запущенных в одном приложении IIS. Значение по умолчанию — 1. Если задать значение 0, число файлов node.exe будет совпадать с числом ЦП на виртуальной машине. Для большинства приложений рекомендуемое значение — 0. Это позволяет использовать все виртуальные ЦП на вашем компьютере. Файл node.exe является однопотоковым, поэтому один такой файл потребляет не более 1 виртуального ЦП. Чтобы добиться максимальной производительности приложения Node, используйте все виртуальные ЦП.

nodeProcessCommandLine

Этот параметр определяет путь к файлу node.exe. Это значение можно задать таким образом, чтобы оно указывало версию файла node.exe.

maxConcurrentRequestsPerProcess

Этот параметр определяет максимальное количество одновременных запросов, отправленных с помощью iisnode в каждый файл node.exe. В службе приложений Azure по умолчанию используется значение Infinite. Его можно изменить с учетом числа запросов, получаемых приложением, и скорости их обработки.

maxNamedPipeConnectionRetry

Этот параметр определяет максимальное число повторных подключений iisnode к именованному каналу для отправки запросов в node.exe. В сочетании с параметром namedPipeConnectionRetryDelay он определяет общее значение времени ожидания каждого запроса в iisnode. В службе приложений Azure для этого параметра по умолчанию задано значение 200. Общее время ожидания в секундах равно произведению maxNamedPipeConnectionRetry *на namedPipeConnectionRetryDelay, разделенному на 1000.

namedPipeConnectionRetryDelay

Этот параметр определяет интервал (в мс), с которым iisnode отправляет повторные запросы в файл node.exe через именованный канал. Значение по умолчанию — 250 мс. Общее время ожидания в секундах равно произведению maxNamedPipeConnectionRetry *на namedPipeConnectionRetryDelay, разделенному на 1000.

По умолчанию общее время ожидания для iisnode в службе приложений Azure составляет 200 * 250 мс = 50 с.

logDirectory

Этот параметр определяет каталог, в который iisnode записывает сведения журналов stdout и stderr. По умолчанию для этого параметра задано значение iisnode. Оно задается относительно основного каталога скрипта (каталога, в котором находится основной файл server.js)

debuggerExtensionDll

Этот параметр определяет версию средства node-inspector, которую iisnode использует при выполнении отладки приложения Node. Сейчас для этого параметра доступны только два значения: iisnode-inspector-0.7.3.dll и iisnode-inspector.dll. По умолчанию для этого параметра задано значение iisnode-inspector-0.7.3.dll. В этой версии используются node-inspector-0.7.3 и веб-сокеты. Чтобы использовать ее, обязательно включите веб-сокеты для веб-приложения Azure. Дополнительные сведения о настройке новой версии node-inspector в iisnode см. по ссылке https://ranjithblogs.azurewebsites.net/?p=98.

flushResponse

По умолчанию перед освобождением ответа или до его завершения (в зависимости от того, что произойдет раньше) IIS помещает в буфер до 4 МБ данных ответа. В iisnode предоставляется параметр конфигурации, который позволяет переопределить это поведение. Чтобы освободить фрагмент тела объекта ответа после того, как iisnode его получит, для атрибута iisnode/@flushResponse в файле web.config необходимо задать значение true:

<configuration>
    <system.webServer>
        <!-- ... -->
        <iisnode flushResponse="true" />
    </system.webServer>
</configuration>

Если вы включите очистку каждого фрагмента в тексте сущности ответа, необходимые для этого дополнительные действия снизят общую пропускную способность системы примерно на 5 % (по данным тестирования версии 0.1.13). Лучше всего применять этот параметр только для тех конечных точек, где требуется потоковая передача ответов (например, с помощью элемента <location> в файле web.config).

Кроме того, в приложениях потоковой передачи для параметра responseBufferLimit обработчика iisnode необходимо задать значение 0.

<handlers>
    <add name="iisnode" path="app.js" verb="\*" modules="iisnode" responseBufferLimit="0"/>
</handlers>

watchedFiles

Разделенный точкой с запятой список файлов, в которых отслеживаются изменения. Любое изменение файла приводит к перезапуску приложения. Каждая запись содержит необязательное имя каталога и обязательное имя файла, которые задаются относительно каталога с основной точкой входа в приложение. Подстановочные знаки можно использовать только в части имени файла. Значение по умолчанию — *.js;iisnode.yml

recycleSignalEnabled

Значением по умолчанию является false. Этот параметр, если он включен, позволяет приложению Node подключаться к определенному каналу (переменная среды — IISNODE_CONTROL_PIPE) и отправлять сообщение о перезапуске. Это приведет к перезапуску процесса w3wp.

idlePageOutTimePeriod

По умолчанию для этого параметра используется значение 0, а это значит, что он отключен. Если задать значение больше 0, iisnode будет выполнять выгрузку всех дочерних процессов с интервалом, указанным для этого параметра (в мс). Дополнительные сведения см. в этой документации. Этот параметр полезен для приложений, которые используют большой объем памяти и могут время от времени выгружать страницы памяти на диск, чтобы освободить ОЗУ.

Предупреждение

Соблюдайте осторожность при включении следующих параметров конфигурации в рабочих приложениях. Эти параметры не рекомендуется включать в активных рабочих приложениях.

debugHeaderEnabled

Значением по умолчанию является false. Если изменить его на true, iisnode добавляет HTTP-заголовок ответа iisnode-debug к каждому отправленному им ответу HTTP. Значение заголовка iisnode-debug имеет формат URL-адреса. Некоторые элементы диагностических данных можно извлечь из фрагмента URL-адреса, а для более детальных сведений вы можете открыть URL-адрес в веб-браузере.

loggingEnabled

Этот параметр управляет ведением журналов stdout и stderr с помощью iisnode. Обработчик iisnode собирает из запущенных в нем процессов Node данные stdout и stderr, а затем записывает их в каталог, определенный в параметре logDirectory. Когда этот параметр включен, приложение записывает журналы в файловую систему, а производительность приложения будет зависеть от объема собранных приложением данных.

devErrorsEnabled

Значением по умолчанию является false. Если изменить его на true, iisnode отобразит в браузере код состояния HTTP и код ошибки Win32. Код win32 полезен при отладке проблем определенных типов.

debuggingEnabled (не включайте этот параметр на активном рабочем сайте)

Этот параметр определяет функцию отладки. В iisnode интегрировано средство node-inspector. Включение этого параметра активирует отладку приложения Node. После включения этого параметра при первом запросе отладки для приложения Node обработчик iisnode создает файлы node-inspector в каталоге debuggerVirtualDir. Средство node-inspector можно загрузить, отправив запрос по адресу http://yoursite/server.js/debug. С помощью параметра debuggerPathSegment можно управлять сегментом URL-адреса отладки. По умолчанию для этого параметра используется значение debug. Если задать для debuggerPathSegment, к примеру, значение GUID, его будет труднее отследить.

См. дополнительные сведения оботладке приложений node.js в Windows.

Сценарии, рекомендации и устранение неполадок

Мое приложение Node отравляет слишком много исходящих вызовов

В рамках своих операций многие приложения попытаются установить с ним исходящие подключения. Например, при получении запроса для его обработки приложению Node потребуется связаться с REST API и получить необходимые для этого сведения. Возможно, при вызовах HTTP или HTTPS понадобится использовать активный агент. При выполнении этих исходящих вызовов в качестве активного агента можно использовать модуль agentkeepalive.

Модуль agentkeepalive следит за тем, чтобы сокеты на виртуальной машине, выполняющей веб-приложение Azure, использовались многократно. Если для каждого исходящего запроса создается новый сокет, нагрузка на приложение возрастает. Применив в приложении механизм повторного использования сокетов для исходящих запросов, вы сможете избежать превышения допустимого числа сокетов (параметр maxSockets), выделяемых для каждой виртуальной машины. В службе приложений Azure мы рекомендуем установить для agentKeepAlive параметр maxSockets со значением 128 сокетов на виртуальную машину (4 экземпляра node.exe*32 maxSocket для каждого экземпляра).

Пример конфигурации модуля agentKeepALive:

let keepaliveAgent = new Agent({
    maxSockets: 32,
    maxFreeSockets: 10,
    timeout: 60000,
    keepAliveTimeout: 300000
});

Важно!

В этом примере предполагается, что на виртуальной машине запущено 4 файла node.exe. Если используется другое количество, параметр maxSockets необходимо изменить соответствующим образом.

Приложение Node потребляет слишком много ресурсов ЦП

На портале может отобразиться оповещение от службы приложений Azure о высоком потреблении ресурсов ЦП. Эти метрики также можно отслеживать, настроив для этого мониторы. Перед проверкой использования ЦП на панели мониторинга портала Azure сначала проверьте максимальные значения ЦП, чтобы не пропустить пиковые значения. Если есть основания полагать, что приложение Node потребляет слишком много ресурсов ЦП, но вы не можете выяснить причину этого, следует выполнить профилирование приложения.

Профилирование приложения Node в службе приложений Azure с помощью средства V8-Profiler

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

const http = require('http');
function WriteConsoleLog() {
    for(let i=0;i<99999;++i) {
        console.log('hello world');
    }
}

function HandleRequest() {
    WriteConsoleLog();
}

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    HandleRequest();
    res.end('Hello world!');
}).listen(process.env.PORT);

Откройте страницу консоли отладки https://yoursite.scm.azurewebsites.net/DebugConsole.

Перейдите в каталог site/wwwroot. Здесь вы увидите интерфейс командной строки, как показано в следующем примере.

Снимок экрана: каталог site/wwwroot и командная строка.

Выполните команду npm install v8-profiler.

Эта команда устанавливает средство v8-profiler и все его зависимости в каталог node_modules. Далее, чтобы выполнить профилирование приложения, измените файл server.js.

const http = require('http');
const profiler = require('v8-profiler');
const fs = require('fs');

function WriteConsoleLog() {
    for(let i=0;i<99999;++i) {
        console.log('hello world');
    }
}

function HandleRequest() {
    profiler.startProfiling('HandleRequest');
    WriteConsoleLog();
    fs.writeFileSync('profile.cpuprofile', JSON.stringify(profiler.stopProfiling('HandleRequest')));
}

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    HandleRequest();
    res.end('Hello world!');
}).listen(process.env.PORT);

Предыдущий код описывает функцию WriteConsoleLog, а затем записывает вывод профиля в файл profile.cpuprofile, расположенный в каталоге site wwwroot. Отправьте запрос в приложение. В каталоге site wwwroot будет создан файл profile.cpuprofile.

Снимок экрана: файл profile.cpuprofile.

Загрузите этот файл и откройте его с помощью средств Chrome (клавиша F12). Нажмите клавишу F12 в Chrome, а затем выберите вкладку Профили и нажмите кнопку Загрузить. Выберите загруженный файл profile.cpuprofile. Щелкните только что загруженный профиль.

Снимок экрана: загруженный файл profile.cpuprofile.

Можно увидеть, что на работу функции WriteConsoleLog ушло 95 % времени. В выходных данных вы также увидите точные номера строк и исходные файлы, которые вызывают проблему.

Чрезмерное потребление памяти приложением Node

Если приложение потребляет слишком много памяти, на портале может появиться уведомление о высоком потреблении памяти от службы приложений Azure. Можно настроить мониторы для отслеживания определенных метрик. Перед проверкой потребления памяти на панели мониторинга портала Azure сначала проверьте максимальный объем памяти, чтобы не пропустить пиковые значения.

Обнаружение утечки и сравнение куч для node.js

Чтобы обнаружить утечки памяти, можно использовать node-memwatch . Установите средство memwatch (так же, как V8-Profiler) и измените код, чтобы извлекать кучи и выявить в них различия, чтобы найти утечки памяти в приложении.

Случайное завершение работы файла node.exe

Node.exe может завершать работу случайным образом по нескольким причинам.

  1. В приложении создаются не перехваченные исключения. Дополнительные сведения о создании исключений можно просмотреть в файле d:\home\LogFiles\Application\logging-errors.txt. В этом файле содержится трассировка стека, которая помогает отлаживать и исправлять приложения.
  2. Приложение потребляет слишком много памяти, и это мешает запустить другие процессы. Когда используемый объем памяти виртуальной машины приближается к 100 %, диспетчер процессов может завершить работу файла node.exe. Диспетчер процессов останавливает некоторые процессы, чтобы остальные получили возможность выполнить свою работу. Чтобы устранить эту проблему, выполните профилирование приложения для поиска утечек памяти. Если приложение требует большого объема памяти, используйте виртуальную машину более высокого уровня (чтобы увеличить доступный объем памяти).

Ошибка запуска приложения Node

Если при запуске приложения возвращаются ошибки с кодом 500, причин может быть несколько:

  1. Файл node.exe находится в неправильном расположении. Проверьте параметр nodeProcessCommandLine.
  2. Основной файл сценария находится в неправильном расположении. Проверьте файл web.config и убедитесь, что в разделе обработчиков задано соответствующее имя основного файла сценария.
  3. Используется неправильная конфигурация файла web.config. Проверьте имена и значения параметров.
  4. Холодный запуск. Приложение запускается слишком долго. Если для запуска приложения требуется больше времени, чем задано для общего времени ожидания в секундах ((maxNamedPipeConnectionRetry * namedPipeConnectionRetryDelay), разделенное на 1000), iisnode возвращает ошибку с кодом 500. Чтобы предотвратить превышение времени ожидания iisnode и возвращение ошибки с кодом 500, увеличьте значения этих параметров для соответствия времени запуска приложения.

Сбой приложения Node

В приложении создаются неперехваченные исключения. Дополнительные сведения об этих исключениях можно просмотреть в файле d:\\home\\LogFiles\\Application\\logging-errors.txt. В этом файле содержится трассировка стека, которая помогает диагностировать и исправлять приложения.

Запуск приложения Node занимает слишком много времени (холодный запуск)

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

  1. Попробуйте выполнить отложенную загрузку node_modules и не загружайте все модули при запуске приложения. Чтобы использовать отложенную загрузку модулей, выполняйте вызов require('module'), только когда модуль становится фактически нужен в функции, то есть перед первым выполнением кода модуля.
  2. В службе приложений Azure используется функция "локальный кэш". С помощью этой функции можно скопировать содержимое сетевой папки на локальный диск виртуальной машины. Так как файлы расположены локально, загрузка node_modules происходит значительно быстрее.

Состояние и подсостояние HTTP обработчика iisnode

В этом исходном файлеcnodeconstants перечислены все возможные сочетания состояний и подсостояний, которые iisnode может возвратить в случае ошибок.

Чтобы отобразить код ошибки Win32, включите для своего приложения FREB (для обеспечения производительности FREB рекомендуется включать только на нерабочих сайтах).

Состояние HTTP Подсостояние HTTP Возможная причина
500 1000 При отправке запроса к iisnode возникла ошибка. Проверьте, запущен ли файл node.exe. Возможно, при запуске этого файла произошел сбой. Проверьте конфигурацию web.config на наличие ошибок.
500 1001 Win32Error 0x2. Приложение не отвечает URL-адресу. Проверьте правила подстановки URL-адреса или определение маршрутов приложения Express. Win32Error 0x6d — именованный канал занят. Файл node.exe не принимает запросы, так как канал занят. Проверьте потребление ресурсов ЦП. Другие ошибки. Проверьте файл node.exe на наличие повреждений.
500 1002 Файл node.exe поврежден. Для трассировки стека проверьте файл d:\home\LogFiles\logging-errors.txt.
500 1003 Проблема с конфигурацией канала. Неправильная конфигурация именованного канала.
500 1004–1018 При отправке запроса к файлу node.exe или обработке ответа от него произошла ошибка. Проверьте файл node.exe на наличие повреждений. Для трассировки стека проверьте файл d:\home\LogFiles\logging-errors.txt.
503 1000 Недостаточно памяти для выделения большего количества подключений по именованным каналам. Проверьте, почему приложение потребляет такое большое количество памяти. Проверьте значение параметра maxConcurrentRequestsPerProcess. Если для него не задано значение Infinite и выполняется много запросов, увеличьте это значение, чтобы предотвратить возникновение этой ошибки.
503 1001 Не удалось отправить запрос к файлу node.exe, так как приложение перезапускается. После перезапуска запросы будут обработаны должным образом.
503 1002 Проверьте фактическую причину в коде ошибки Win32. Не удается отправить запрос к файлу node.exe.
503 1003 Именованный канал перегружен. Проверьте, не потребляет ли Node.exe слишком много ресурсов ЦП.

NODE.exe поддерживает параметр с именем NODE_PENDING_PIPE_INSTANCES. В службе приложений Azure для этого параметра задано значение 5000. Это означает, что файл node.exe в именованном канале может принять 5000 запросов за раз. Этого достаточно для большинства приложений Node, запущенных в службе приложений Azure. В службе приложений Azure вы вряд ли увидите значение 503.1003, так как для NODE_PENDING_PIPE_INSTANCES задается высокое значение.

Дополнительные ресурсы

Дополнительные сведения о приложениях Node.js в службе приложений Azure см. по следующим ссылкам.