Если можете, никогда не запускайте Node.js непосредственно в рабочей среде.

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

Иногда я также задаюсь вопросом, действительно ли я много знаю.

Всего несколько недель назад я разговаривал с другом, и он небрежно упомянул: «Вы никогда не будете использовать Node напрямую для запуска программы в продакшене». Я решительно кивнул, показывая, что ятакжеНе запускать Node непосредственно в продакшене по причинам, которые, вероятно, всем известны. Но я не знаю, должен ли я знать, почему? Могу ли я по-прежнему писать код?

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

Кстати, чем старше я становлюсь, тем меньше становится эта точка.

Alicia LiuСоздал лучшую диаграмму и изменил мою жизнь. Она сказала, что ситуация больше похожа на...

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

Слишком драматично. Виновата Пандора. Когда я пишу это, я не могу контролировать то, что произойдет дальше. иDashboard ConfessionalКакой яд.

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

Прежде всего, давайте проясним аргумент «Никогда не запускайте программу непосредственно из узла».

Никогда не запускайте Node непосредственно в рабочей среде

Это утверждение может быть, а может и не быть правдой. Давайте рассмотрим, как появилось это утверждение. Во-первых, давайте посмотрим, почему это неправильно.

Предположим, у нас есть простой экспресс-сервер. Самый простой сервер Express, о котором я могу думать, выглядит следующим образом:

const express = require("express");
const app = express();
const port = process.env.PORT || 3000;

// 查看 http://localhost:3000
app.get("/", function(req, res) {
  res.send("Again I Go Unnoticed");
});

app.listen(port, () => console.log(`Example app listening on port ${port}!`));

определяя вpackage.jsonв сценарии запуска, чтобы запустить его.

"scripts": {
  "start": "node index.js",
  "test": "pfffft"
}

Здесь есть две проблемы. Первая — это проблема разработки, а вторая — производственная проблема.

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

Обычно мы используем какой-нибудь менеджер процессов Node, например.supervisorилиnodemonДля решения этой проблемы. Эти пакеты будут слушать наш проект и перезапускать сервер, когда мы фиксируем изменения. Я обычно делаю.

"scripts": {
  "dev": "npx supervisor index.js",
  "start": "node index.js"
}

затем бегиnpm run dev. Обратите внимание, что я бегу здесьnpx supervisor, что позволяет нам установитьsupervisorиспользуйте его в случае пакета.

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

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

const express = require("express");
const app = express();
const fs = require("fs");
const port = process.env.PORT || 3000;

// 查看 http://localhost:3000
app.get("/", function(req, res) {
  res.send("Again I Go Unnoticed");
});

app.get("/read", function(req, res) {
  // 这个路由不存在
  fs.createReadStream("my-self-esteem.txt");
});

app.listen(port, () => console.log(`Example app listening on port ${port}!`));

Если мы запустим непосредственно против Nodenpm startи перейдите кreadEndpoint, страница сообщит об ошибке, поскольку файл не существует.

Ничего страшного, верно? Это просто ошибка, которая произошла.

Нет. Это важно. Если вы вернетесь к терминалу, то увидите, что приложение полностью закрылось.

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

Это плохо. Это то, что говорят люди«Никогда не запускайте Node напрямую в продакшене»

хорошо. Если мы не можем запустить Node напрямую в продакшене, как правильно запустить Node в продакшене?

Опции для узла в производстве

У нас есть несколько вариантов.

Один из них - просто использовать в производстве что-то вродеsupervisorилиnodemonинструменты, как мы используем их в разработке. Это работает, но инструменты немного легковесны. Лучшим вариантом является pm2.

поддержка pm2

pm2 — это менеджер процессов Node со множеством полезных функций. Как и любую другую библиотеку "JavaScript", вы можете использоватьnpmУстановите его глобально - или вы можете использовать его сноваnpx. Я не буду здесь вдаваться в подробности.

Есть много способов запускать программы с помощью pm2. Самый простой - вызвать в файле вводаpm2 start.

"scripts": {
  "start": "pm2 start index.js",
  "dev": "npx supervisor index.js"
},

Терминал отобразит это:

Это процесс, который мы запускаем в фоновом режиме под наблюдением pm2. если вы посетитеreadКонечная точка разбила программу, а PM2 автоматически перезапустит его. Вы ничего не увидите в терминале, потому что он работает на заднем плане. Если вы хотите увидеть, что делает PM2, вы можете запуститьpm2 log 0. это0Мы хотим увидеть идентификатор журнала процесса.

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

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

"scripts": {
  "start": "pm2 start index.js --watch",
  "dev": "npx supervisor index.js"
},

Обратите внимание: поскольку pm2 работает в фоновом режиме, вы не можете просто передатьctrl+cчтобы убить запущенный процесс pm2. Вы должны остановить процесс, передав ему его идентификатор или имя.

pm2 stop 0

pm2 stop index

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

Если вы хотите удалить эту ссылку на процесс, вам нужно запуститьpm2 delete. вы можете использовать командуdeleteостанавливать и удалять процессы.

pm2 delete index

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

Несколько процессов, использующих режим форка pm2

pm2 имеет множество параметров конфигурации, которые содержатся в файле «экосистемы». можно сделать, запустивpm2 initсоздать один. Вы получите следующее:

module.exports = {
  apps: [
    {
      name: "Express App",
      script: "index.js",
      instances: 4,
      autorestart: true,
      watch: true,
      max_memory_restart: "1G",
      env: {
        NODE_ENV: "development"
      },
      env_production: {
        NODE_ENV: "production"
      }
    }
  ]
};

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

Раздел Applications определяет приложения, которые вы хотите запускать и отслеживать с помощью pm2. Вы можете запустить более одного приложения. Многие из этих параметров конфигурации могут говорить сами за себя. На чем я хочу сосредоточиться, так этопримернастраивать.

pm2 может запускать несколько экземпляров вашего приложения. Вы можете передать столько экземпляров, сколько хотите запустить, и pm2 может запустить их все. Итак, если мы хотим запустить 4 экземпляра, мы можем создать следующий файл конфигурации.

module.exports = {
  apps: [
    {
      name: "Express App",
      script: "index.js",
      instances: 4,
      autorestart: true,
      watch: true,
      max_memory_restart: "1G",
      env: {
        NODE_ENV: "development"
      },
      env_production: {
        NODE_ENV: "production"
      }
    }
  ]
};

Затем мы используемpm2 startзапустить его.

PM2 теперь будет работать в «кластерном» режиме. Каждый из этих процессов будет работать на разных процессорах моего компьютера, в зависимости от количества имеющихся у меня ядер. Если мы хотим запустить процесс для каждого ядра, не зная нескольких ядер, мы можемmaxпараметр, переданныйinstancesпараметры для настройки.

{
   ...
   instances: "max",
   ...
}

Посмотрим, сколько ядер у меня на этой машине.

8 ядер! Ух ты. Я собираюсь установить Subnautica на свой компьютер с дистрибутивом Microsoft. Не говори им, что я это сказал.

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

Вы можете делать гораздо больше с pm2, включая мониторинг и другие действия с этими надоедливымиenvironment variables.

Еще одно замечание: если по какой-то причине вы хотите запустить pm2npm startинструкция. Вы можете сделать это, запустив npm как процесс и передав-- start. Пространство перед «началом» здесь очень важно.

pm2 start npm -- start

существуетAzure AppService, включает pm2 в фоновом режиме по умолчанию. Если вы хотите использовать pm2 в Azure, вам не нужно включать его вpackage.jsonв файле. Вы можете добавить файл экосистемы, и все готово.

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

Запуск непосредственно против Node в продакшене

У меня были некоторые вопросы по этому поводу, поэтому я связалсяTierney Cyren, который является частью огромного оранжевого круга знаний, особенно когда речь идет о Node.

Тирни отмечает, что использование диспетчера процессов на основе Node, такого как pm2, имеет некоторые недостатки.

Основная причина в том, что Node не следует использовать для мониторинга Node. Вы, конечно, не хотите контролировать себя с помощью того, что вы контролируете. Как вы попросили моего сына-подростка проконтролировать себя в пятницу вечером: плохо ли получится? Может быть, а может и нет. .

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

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

Как оказалось, Azure уже это делает. Если мы не отправим файлы экосистемы pm2 в Azure, он будет использовать нашpackage.jsonфайл для запуска скрипта для запуска приложения, которое мы можем запустить непосредственно на Node.

"scripts": {
  "start": "node index.js"
}

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

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

В идеале вы хотите запустить несколько контейнеров. Решение состоит в том, чтобы развернуть несколько экземпляров приложения на нескольких сайтах Azure AppService, а затем использовать Azure Front Door для балансировки нагрузки приложения под одним IP-адресом. Front Door знает, когда контейнер не работает, и направляет трафик на другие работоспособные экземпляры приложения.

Azure Front Door Service | Microsoft Azure
Доставляйте, защищайте и отслеживайте производительность глобально распределенных приложений микрослужб с помощью Azure Front Door.

systemd

Другое предложение от Tierney заключается в использованииsystemdЗапустить узел. Я действительно не знаю (или не знаю вообще)systemd, однажды я пропустил это предложение, поэтому перескажу словами Тирни:

Этот вариант возможен только в том случае, если у вас есть доступ к Linux в вашем развертывании и вы контролируете запуск Node на уровне службы. Если вы запускаете процессы node.js на долго работающей виртуальной машине Linux, такой как виртуальная машина Azure, запуск node.js с systemd — хороший выбор. Вы можете избежать этого варианта, если вы просто развертываете файл в такой службе, как Azure AppService или Heroku, или работаете в контейнерной среде, такой как Azure Container Instances.

Рабочий поток Node.js

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

Будьте зрелым разработчиком

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

малый круг навсегда

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

Дополнительные сведения о pm2, Node и Azure см. в следующих ресурсах:

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


Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.