Мониторинг производительности среды Node.js

Node.js

Introduction

Node прошел долгий путь с выпуском версии Node v11.0. На основе Node существует множество серверных фреймворков, которые помогают нам разрабатывать и развертывать интерфейсные проекты независимо от серверных.

Миграция бизнес-логики и появление моделей рендеринга на стороне сервера различных сред MV* делают стратегии внешнего SSR на основе Node более зависимыми от производительности сервера. Производительность первого экрана и стабильность службы Node напрямую влияют на взаимодействие с пользователем. Как серверный язык, по сравнению со старыми серверными языками, такими как Java и PHP, общий контроль производительности Node все еще не идеален. Хотя существует платформа сигнализации, такая как часовой, для своевременного уведомления об ошибках, она не может предотвратить возникновение ошибок. Как предотвратить проблемы до того, как они произойдут, сначала нужно понять основные показатели мониторинга производительности Node.js.

Следующий код основан на платформе Egg.Если вы не знакомы с Egg, вы можете сначала просмотреть документацию.

показатель

Узкие места сервера в основном включают следующее:

  1. CPU
  2. ОЗУ
  3. диск
  4. I/O
  5. Интернет

Учитывая разные среды Node, типы требований к ресурсам также различаются. Если Node используется только для внешнего SSR, то ЦП и сеть будут основными узкими местами производительности.

Конечно, если вам нужно использовать Node для работы, связанной с сохранением данных, то объем операций ввода-вывода и использование диска также будут высокими.

Даже компании с очень продвинутой фронтенд-разработкой редко используют Node в качестве поддержки бизнес-данных. В лучшем случае он используется как уровень BFF для предоставления услуг данных для внешнего интерфейса и не связывается напрямую с постоянными данными. Таким образом, диск и ввод-вывод вряд ли станут узким местом текущей производительности внешнего интерфейса.

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

Таким образом, в большинстве сценариев можно сказать, что ЦП, память и сеть являются основными узкими местами производительности Node.

Показатели ЦП

Загрузка ЦП и использование ЦП

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

  • Загрузка ЦП: перспектива процесса
  • Использование ЦП: распределение процессорного времени

Процесс — это наименьшая единица распределения ресурсов.

Это предложение встречается более или менее в учебниках по операционным системам или в ваших экзаменационных работах. То есть система распределяет ресурсы в соответствии с уровнем процессов, и одно ядро ​​ЦП может одновременно обслуживать только 4 процесса.

Затем хорошо понимается загрузка ЦП.В течение определенного периода времени общее количество процессов, занимающих и ожидающих ЦПЭто средняя загрузка ЦП за этот период времени.В большинстве случаев мы называем этот стандарт какloadavg.

Загрузка ЦП (использование ЦП) предназначена для количественной оценки занятости ЦП.Как правило, мы считаем, что загрузка ЦП = 1 - время простоя ЦП (время простоя) / общее время ЦП.

Это было очень четко объяснено на вики, пожалуйста, принесите свою собственную тизи

Количественные показатели ЦП

Итак, какой из этих двух индикаторов лучше всего отражает фактическое состояние системы?

Слайд: ЦП

люди: процесс

Предположим, есть 4 слайда. На каждой горке может разместиться до 10 человек. Мы предполагаем, что все люди одного размера. Тогда можно получить следующую аналогию:

  • Loadavg = 0, значит на слайде никого нет

  • Loadavg = 0,5, что означает, что среднее количество людей на каждом слайде составляет половину слайда, то есть всего на слайде находится 20 человек.Из-за стратегии планирования ЦП эти люди обычно распределяются равномерно (все выберет слайд с меньшим количеством людей)

  • Loadavg = 1, что означает, что все слайды заполнены, свободного места нет.

  • Loadavg = 2, что означает, что не только каждая горка заполнена людьми, но и 40 человек ждут позади

Приведенные выше аналогии основаны на мгновенной средней нагрузке.

Как правило, для количественной оценки loadavg мы используем три разных стандарта времени. 1 минута, 5 минут и 15 минут.

1-минутный индикатор трудно получить более сбалансированный индикатор. Поскольку 1 минута слишком коротка, пик в секунду может повлиять на средний показатель за 1-минутный период. Однако, если loadavg внезапно достигает очень высокого значения в течение 1 минуты, это также может быть предвестником сбоя системы, а также индикатором, требующим бдительности.

5 минут и 15 минут — более подходящие оценочные показатели. Когда процессор продолжает работать с высокой нагрузкой в ​​течение 5 или 15 минут, это очень опасно для всей системы. Любой, кто столкнулся с пробкой, должен знать, что если пробка возникает, пока пробка не будет устранена вовремя, пробка будет становиться все длиннее и длиннее. То же самое справедливо и для ЦП: если процессы, ожидающие на ЦП, заблокированы больше, задачи, которые встают в очередь позже, не смогут захватить ресурсы и будут заблокированы все время.

На MAC вы можете использовать привилегии rootsysctl -n vm.loadavgчтобы получить.

// /app/lib/cpu.js
const os = require('os');
// cpu核心数
const length = os.cpus().length;
// 单核CPU的平均负载
os.loadavg().map(load => load / length);

Использование ЦП не является хорошим значением в качестве критерия прямой оценки.Поскольку процессы блокируются на ЦП по разным причинам, для задач с интенсивным использованием ЦП загрузка ЦП может быть хорошим индикатором текущей работы ЦП, но для задач с интенсивным вводом-выводом бездействие ЦП не означает, что ЦП бездействует. Делать нечего, может задача приостановлена ​​для других операций.

Однако для системы Node, которая выполняет SSR, рендеринг в основном можно рассматривать как бизнес с интенсивным использованием ЦП, поэтому этот показатель может в определенной степени отражать производительность ЦП в текущей бизнес-среде.

// /app/lib/cpu.js

const os = require('os');
// 获取当前的瞬时CPU时间
const instantaneousCpuTime = () => {
    let idleCpu = 0;
    let tickCpu = 0;
    const cpus = os.cpus();
    const length = cpus.length;

    let i = 0;
	  while(i < length) {
      let cpu = cpus[i];

      for (let type in cpu.times) {
        tickCpu += cpu.times[type];
      }

      idleCpu += cpu.times.idle;
      i++;
    }

    const time = {
      idle: idleCpu / cpus.length,  // 单核CPU的空闲时间
      tick: tickCpu / cpus.length,  // 单核CPU的总时间
    };
	  return time;
}
const cpuMetrics = () => {
  const startQuantize = instantaneousCpuTime();
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const endQuantize = instantaneousCpuTime();
      const idleDifference = endQuantize.idle - startQuantize.idle;
      const tickDifference = endQuantize.tick - startQuantize.tick;

  		resolve(1 - (idleDifference / tickDifference));
    }, 1000);
  });
};

cpuMetrics().then(res => {
    console.log(res);
	// 0.074999
});

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

показатели памяти

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

// /app/lib/memory.js
const os = require('os');
// 获取当前Node内存堆栈情况
const { rss, heapUsed, heapTotal } = process.memoryUsage();
// 获取系统空闲内存
const sysFree = os.freemem();
// 获取系统总内存
const sysTotal = os.totalmem();

module.exports = {
  memory: () => {
    return {
      sys: 1 - sysFree / sysTotal,  // 系统内存占用率
      heap: heapUsed / headTotal,   // Node堆内存占用率
      node: rss / sysTotal,         // Node占用系统内存的比例
    }
  }
}

дляprocess.memoryUsage()Есть несколько вещей, которые следует помнить о полученном значении:

Моя книга по просвещению по Node "Introduction to Node.js" - это книга, хотя версия отставала от текущего Node.js на много выпусков, но содержание о механизме GC движка V8 по-прежнему очень полезно, всем рекомендую купить Подлинная поддержка г-н Пак Линг.

  1. rss: указывает общий объем памяти, занимаемый процессом узла.
  2. heapTotal: указывает общий объем динамической памяти.
  3. heapUsed: фактическое использование памяти кучи.
  4. external: использование памяти внешними программами, включая использование памяти программами C++, которые включают ядра Node.

Первое, на что следует обратить внимание, — это стек памяти, то есть использование памяти в куче. В однопоточном режиме Node программа C++ (движок V8) будет запрашивать определенный объем памяти для Node в качестве ресурса памяти потока Node.heapTotal. Во время использования нашего узла новые объявленные переменные будут использовать эту память для храненияheapUsed.

Алгоритм сборки мусора Node в определенной степени будет тратить некоторые ресурсы памяти, поэтому, когдаheapUsedдостигатьheapTotalВ половине случаев вы можете принудительно запустить операцию GCglobal.gc().Для операции gc, пожалуйста, прочитайте эту статью.Для мониторинга и обработки системной памяти невозможно выполнять операции GC точно так же, как уровень памяти Node, но также необходимо выполнить понижение уровня рендеринга. 70% ~ 80% использования памяти — очень опасная ситуация. Конкретное значение должно быть определено в соответствии с хостом, на котором расположена среда.

В частности, связанные со стратегией GC и правилами распределения памяти Node, вы можете увидетьStrongLoop - Node.js Performance Tip of the Week: Managing Garbage Collection.

QPS

Строго говоря, QPS нельзя использовать в качестве прямого стандарта веб-мониторинга. Однако, когда сервер находится под высокой нагрузкой и не может получить QPS, близкий к таковому при стресс-тесте, необходимо учитывать, что какие-то другие причины приводят к узким местам в производительности сервера. Как правило, при выполнении SSR в среде Node, предполагая, что максимальное количество потоков в Node-Cluster равно 10, можно параллельно отображать 10 страниц.Конечно, это также зависит от количества ядер центрального процессора.

В случае использования Node в качестве хост-среды для SSR легко записать количество запросов, на которые текущая машина отвечает в течение определенного периода времени. Когда я писал дипломную работу, я попробовал несколько способов стресс-тестирования веб-сайтов.

ApacheBench

http_load

Seige

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

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

тестовое задание

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

Среда Node, запущенная локально, представляет собой среду React SSR, расширенную на основе платформы Egg.В реальной онлайн-среде многие статические ресурсы (включая сценарии javascript, css, изображения и т. д.) передаются в CDN, поэтому эти ресурсы не будут напрямую оказывать давление на среду, и между производственной средой и средой разработки существует много различий в процессах, поэтому фактическая производительность намного лучше, чем при локальном запуске. Для удобства тестирования здесь проект Egg запускается непосредственно локально.

тестовая среда

Вы можете использовать PM2 для локального запуска проекта Node или запустить его напрямую с помощью команды Node. Старайтесь не использовать среду разработки, такую ​​как webpack-dev-server, для запуска в локальной тестовой среде. Это может привести к тому, что режим кластера Node чтобы не работать должным образом Мониторинг потоков Блокировать поток рендеринга страницы. Можно использовать среды на основе яиц.scheduleЗапланированные задачи для регулярной печати журналов мониторинга среды. Для конкретного использования см. документацию Egg, которая будет написана более подробно. Затем настройте тип журнала для хранения журналов мониторинга независимо от журналов приложений для упрощения анализа и визуализации.

// /app/schedule/monitor.js
const memory = require('../lib/memory');
const cpu = require('../lib/cpu');

module.exports = app => {
  return {
    schedule: {
	    interval: 10000,
      type: 'worker',
	  },
    async task(ctx) {
      ctx.app.getLogger('monitorLogger').info('你想打印的日志结果')
    }
  }
}


// /config/config.prod.js
const path = require('path');
// 自定义日志,将日志文件自定义到一个单独的监控日志文件中
module.exports = appInfo => {
  return {
    customLogger: {
       monitorLogger: { file: path.resolve(__dirname, '../logs/monitor.log') }
    }
  }
}

Затем подготовьте осаду к стресс-тестированию:Установить осаду на Mac

Или на MAC проще использоватьbrewустановить напрямуюsiege. Этот метод рекомендуется, потому что это может произойти, если вы напрямую загрузите исходный пакет и скомпилируете его.libsslПроблема в том, что библиотеку нельзя слинковать, в результате невозможно делать https запросы.

Тестируйте и отслеживайте результаты

  • Без запроса доступа:

日志

  • siege

Настройте список URL-адресов запроса на осаду: мы можем поместить URL-адрес, который мы хотим запросить на осаду, в файл и прочитать его с помощью команды siege (здесь следует отметить, что siege может получить доступ только к http-сайтам, если сайт использует https, другие методы могут нужно учитывать).

URL-адрес файла

urls

воплощать в жизнь:siege -c 10 -r 5 -f urls -i -b

-c: имитировать одновременный доступ n пользователей

-r: повторить тест n раз

-f: указать файл выборки для тестового URL.

-I: указать произвольный URL-адрес для получения URL-адреса в файле.

-b: запрос без ожидания

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

开始siege

siege结果

Видно, что siege совершил 515 обращений к серверу, так как помимо главной страницы у сервера есть еще какие-то статические ресурсы для запроса, в том числе страницы, javascript-скрипты, картинки и css и т. д. Среднее время отклика каждого ресурс 0,83 секунды

Время окончания запроса20:29:37, можно заметить, что по прошествии этого времени все показатели процессора стали снижаться, а память существенно не изменилась.

Еще один стресс-тест:

воплощать в жизнь:siege -c 100 -r 5 -f urls -i -b, увеличьте количество параллелизма до 10 раз, то есть до 100 параллелизма.

Видно, что среднее время отклика снизилось до 3,85 секунды, что очень заметно. а такжеloadavgПо сравнению с первым стресс-тестом наблюдается очень значительный прирост. Использование памяти не сильно меняется,

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

Заинтересованные друзья могут попробовать экстремальный ОРЗ автомата. Или попробуйте стресс-тест на физической машине. Я не посмел так обидеть своего младшего брата.

Conclusion

Сейчас многие бизнесы начинают переходить на фронтенд, и многие команды начали постепенно пробовать внедрять концепцию BFF (бэкенды для фронтендов). Пусть бэкэнд сосредоточится на предоставлении единой модели данных, затем перенесет бизнес-логику на уровень BFF на основе Node.js, а фронтенд предоставит себе API-интерфейс, что оставляет много затрат для фронтенда и бэкенда. конечная совместная отладка Предоставленный интерфейс RPC или HTTP является более общим, требует меньше модификации серверных проектов и ускоряет эффективность разработки.

Однако это очень зависит от стабильности на стороне узла.В архитектуре BFF, если на стороне узла возникает ошибка, вызывающая блокировку, все внешние страницы перестают обслуживаться, что приводит к серьезным последствиям, поэтому мониторинг Сторона узла становится все более и более значимой. Сочетание некоторых традиционных платформ, таких как sentry или zabbix, может помочь создать стабильную среду развертывания переднего плана.

Ссылаться на

Несколько инструментов стресс-тестирования производительности веб-сервера

Node.js Garbage Collection Explained

Pattern: Backends For Frontends

Node.js Performance Monitoring - Part 1: The Metrics to Monitor

Node.js Performance Monitoring - Part 2: Monitoring the Metrics

What is loadavg

Using LoadAvg for Performance Optimization