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

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

Обнаружение ошибок и простоев с помощью продуктов APM

Продукты для мониторинга и производительности приложений (APM) проверяют нашу кодовую базу и API, чтобы выйти за рамки традиционного мониторинга и измерить общее взаимодействие с пользователем по сервисам и уровням.

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

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

Сделайте наш код готовым к работе

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

Измерение и защита использования памяти

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

Инструмент APM также может помочь в этом. Для приложений Express мы можем добавить пакет express-status-monitor, чтобы отслеживать состояние нашего приложения, включая использование ЦП и памяти, время отклика, количество запросов в секунду и многое другое.

Нам просто нужно установить пакет, запустив:

npm i express-status-monitor

Затем мы можем использовать его, написав следующий код:

const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(require('express-status-monitor')());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res, next) => {
  res.send('hello')
});
app.listen(3000, () => console.log('server started'));

Мы просто помещаем пакет прямо в наше приложение с помощью app.use(require(‘express-status-monitor’)());.

Затем, когда мы перейдем на страницу /status, мы увидим все перечисленные показатели производительности и состояния.

Получение ресурсов внешнего интерфейса из узла

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

Если мы переместим их на другой сервер, мы не будем связывать наше приложение Node, обслуживая сотни файлов HTML, CSS, JavaScript и мультимедиа.

Будьте без гражданства и убивайте наши серверы почти каждый день

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

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

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

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

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

Назначьте идентификатор транзакции каждому оператору журнала

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

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

const express = require('express');
const bodyParser = require('body-parser');
const morgan = require('morgan')
const uuid = require('uuid')
const fs = require('fs');
const path = require('path');
morgan.token('id', (req) => {
  return req.id
})
const app = express();
app.use((req, res, next) => {
  req.id = uuid.v4()
  next()
})
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' })
app.use(morgan(':id :method :url :response-time', { stream: accessLogStream }))
app.get('/', (req, res, next) => {
  res.send('hello');
});
app.listen(3000, () => console.log('server started'));

В приведенном выше коде мы добавили собственное промежуточное ПО, чтобы установить req.id в UUID. Затем мы записываем это в файл вместе со временем ответа.

Заключение

Мы можем добавить мониторинг в наше приложение с помощью продуктов APM. Чтобы освободить наше приложение от ненужной работы, мы должны переместить наши внешние ресурсы из нашего приложения Node. Кроме того, приложения Node не должны иметь состояния. Мы можем добиться этого, убивая и перестраивая сервер каждый день. Это предотвращает проблемы с потерей данных, которые нам нужны на сервере.

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