Node.js — популярная среда выполнения для создания быстрых, масштабируемых и эффективных веб-приложений. Однако, несмотря на присущие ему сильные стороны, плохо оптимизированные приложения Node.js могут страдать от узких мест в производительности, что приводит к медленной загрузке, отказу серверов и увеличению эксплуатационных расходов. Чтобы максимизировать потенциал вашего приложения Node.js и убедиться, что оно может безотказно справляться с высоким уровнем трафика, важно оптимизировать его производительность. В этом руководстве мы рассмотрим некоторые эффективные методы оптимизации производительности вашего приложения Node.js, от анализа показателей производительности до реализации стратегий кэширования и использования других передовых методов. К концу этого руководства у вас будет полное представление о том, как повысить производительность вашего приложения Node.js и обеспечить превосходное взаимодействие с пользователем.

Предпосылки

Руководство

Наше приложение Node.js находится здесь — https://github.com/pavanbelagatti/Simple-Node-App

Вы можете увидеть app.js в корне репозитория приложения,

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3002;
app.get('/', (request, response) => {
  response.status(200).json({
    message: 'Hello Docker!',
  });
});
app.listen(PORT, () => {
  console.log(`Server is up on localhost:${PORT}`);
});

Вы можете запустить приложение, используя следующую команду:

node app.js

Теперь давайте поговорим об оптимизации производительности этого приложения.
Вот несколько приемов, которые вы можете использовать:

Кэширование:

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

Используйте асинхронный код:

В Node.js асинхронный код может помочь повысить производительность вашего приложения.

Используйте кластерный модуль:

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

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

Вот обновленный файл app.js

const express = require('express');
const cluster = require('cluster');
const numCPUs = require('os').cpus().length;
const NodeCache = require( "node-cache" );
const app = express();
const cache = new NodeCache();
const PORT = process.env.PORT || 3002;
// Define a function to handle the request
const handleRequest = (request, response) => {
  // Check if the request is already cached
  const key = request.url;
  const cachedResponse = cache.get(key);
  if (cachedResponse) {
    // If the response is cached, return it
    console.log(`Serving from cache: ${key}`);
    return response.status(200).json(cachedResponse);
  }
  // If the response is not cached, perform the operation asynchronously
  console.log(`Processing request: ${key}`);
  setTimeout(() => {
    const responseData = {
      message: 'Hello Docker!',
    };
    cache.set(key, responseData);
    console.log(`Caching response: ${key}`);
    return response.status(200).json(responseData);
  }, 1000);
};
// Use clustering to take advantage of multiple CPU cores
if (cluster.isMaster) {
  console.log(`Master ${process.pid} is running`);
  // Fork workers
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
  // Listen for worker exit events
  cluster.on('exit', (worker, code, signal) => {
    console.log(`Worker ${worker.process.pid} died`);
  });
} else {
  // Set up the server
  app.get('/', handleRequest);
  app.listen(PORT, () => {
    console.log(`Worker ${process.pid} is up on localhost:${PORT}`);
  });
}

Зависимость node-cache отсутствует. Добавьте его с помощью приведенной ниже команды

npm install node-cache

Вы можете запустить приложение с помощью той же команды

node app.js

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

Приведенный выше код включает следующие оптимизации:

  • Кэширование с использованием модуля node-cache. Мы создаем новый экземпляр node-cache и используем его для хранения ответов на каждый URL-адрес запроса. Когда приходит новый запрос, мы сначала проверяем, не закэширован ли уже ответ. Если это так, мы возвращаем кешированный ответ вместо создания нового ответа.
  • Асинхронный код: мы используем функцию setTimeout для имитации асинхронной операции, выполнение которой занимает 1 секунду. Это позволяет серверу продолжать обработку запросов во время выполнения асинхронной операции.
  • Модуль кластера. Мы используем модуль кластера для создания рабочего процесса для каждого ядра ЦП. Это позволяет серверу одновременно обрабатывать несколько запросов и использовать все доступные ядра ЦП.

Давайте проверим производительность старого и оптимизированного сервера.

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

Вот пример того, как вы можете использовать Siege для проверки производительности ваших серверов:
Установите Siege: вы можете установить Siege с помощью следующей команды в системах на основе Unix:

sudo apt-get install siege

А для MAC вы можете использовать приведенную ниже команду для установки Siege.

brew install siege

После установки Siege вы можете запустить следующую команду, чтобы имитировать 100 одновременных пользователей, делающих 1000 запросов к вашему серверу:

siege -c 100 -r 1000 http://localhost:3002/

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

node app.js

Затем запустите команду Curl, чтобы измерить время отклика.

time curl http://localhost:3002/

Смотрите результаты ниже

Результат можно разбить на следующие компоненты:

  • Пользователь 0,00 с: это количество времени, которое ЦП потратил на выполнение пользовательского кода (т. е. время, затраченное на выполнение вашего кода JavaScript).
  • Система 0,00 с: это количество времени, затраченное ЦП на выполнение системного кода (т. е. время, затраченное на выполнение кода в операционной системе или другого кода системного уровня). .
  • 39% ЦП: это процент использования ЦП во время выполнения кода.
  • Всего 0,018: это общее время, которое потребовалось для выполнения кода (т. е. время пользователя + системное время).

Теперь давайте сравним производительность со старым сервером.
Используйте тот же метод, только убедитесь, что ваш старый сервер (app.js) работает на локальном порту 3001 для этого эксперимента.

Запустите приложение

node app.js

Добавьте нагрузку с Siege

siege -c 100 -r 1000 http://localhost:3001/

Затем запустите команду Curl, чтобы измерить время отклика.

time curl http://localhost:3001/

Смотрите результаты ниже,

  • Затраты ЦП на выполнение кода: 0,00 с
  • Время, затрачиваемое на выполнение системного кода: 0,01 с
  • % использования ЦП для выполнения кода: 51%
  • Время выполнения кода: 0,020

Очевидно и более очевидно, какой сервер более оптимизирован.

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

Первоначально опубликовано на https://dev.to 3 апреля 2023 г.

👋 Если вы считаете это полезным, пожалуйста, несколько раз нажмите кнопку аплодисментов 👏 ниже, чтобы выразить свою поддержку автору 👇

🚀Присоединяйтесь к сообществу разработчиков FAUN и получайте похожие истории в свой почтовый ящик каждую неделю