Node.js на многоядерных машинах
Node.js выглядит интересно, НО Я должен что-то пропустить - не Node.js настроен только для запуска на одном процессе и потоке?
Тогда как он масштабируется для многоядерных ЦП и многопроцессорных серверов? В конце концов, все отлично сделать быстрый, насколько возможно, сервер с одним потоком, но для высоких нагрузок я хотел бы использовать несколько процессоров. То же самое можно сказать и о том, что быстрее делать приложения - кажется, сегодня используется несколько процессоров и распараллеливает задачи.
Как Node.js вписывается в это изображение? Является ли его идея каким-то образом распространять несколько экземпляров или что?
Ответы
Ответ 1
[Этот пост обновлен с 2012-09-02 (новее, чем указано выше).]
Node.js абсолютно масштабируется на многоядерных машинах.
Да, Node.js - однопоточный процесс. Это очень продуманное дизайнерское решение и устраняет необходимость использования семантики блокировки. Если вы не согласны с этим, вы, вероятно, еще не осознаете, насколько безумно сложно отлаживать многопоточный код. Для более глубокого объяснения модели процесса Node.js и почему он работает таким образом (и почему он НИКОГДА не поддерживает несколько потоков), прочитайте мой другой пост.
Итак, как я могу использовать 16-ядерный ящик?
Два способа:
- Для больших тяжелых вычислительных задач, таких как кодирование изображений, Node.js может запускать дочерние процессы или отправлять сообщения дополнительным рабочим процессам. В этом дизайне у вас будет один поток, управляющий потоком событий, и N процессов, выполняющих тяжелые вычислительные задачи и пережевывающие другие 15 процессоров.
- Для масштабирования пропускной способности в веб-сервисе вы должны запускать несколько серверов Node.js на одном поле, по одному на ядро и трафик между ними. Это обеспечивает отличную совместимость с процессором и масштабирует пропускную способность почти линейно с подсчетом ядра.
Масштабирование пропускной способности в веб-сервисе
Так как v6.0.X Node.js включил кластерный модуль прямо из коробки, что позволяет легко установить несколько рабочих node, которые могут прослушивать один порт. Обратите внимание, что это НЕ то же самое, что и старый модуль "cluster" для обучения, доступный через npm.
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
} else {
http.Server(function(req, res) { ... }).listen(8000);
}
Рабочие будут соревноваться, чтобы принимать новые соединения, и наименее загруженный процесс, скорее всего, победит. Он работает очень хорошо и может значительно увеличить пропускную способность на многоядерном ящике.
Если у вас достаточно нагрузки, чтобы заботиться о нескольких ядрах, вам также захочется сделать еще несколько вещей:
-
Запустите службу Node.js за веб-прокси, например Nginx или Apache - что-то, что может делать дросселирование соединения (если вы не хотите, чтобы условия перегрузки полностью вывели окно), переписывайте URL-адреса, статичный контент и прокси-сервер других под-сервисов.
-
Периодически перерабатывайте рабочие процессы. Для долговременного процесса даже небольшая утечка памяти в конечном итоге будет складываться.
-
Сбор/мониторинг журнала установки
PS: Там обсуждается Аарон и Кристофер в комментариях другого поста (на момент написания этой статьи, его главной должности). Несколько комментариев по этому поводу:
- Общая модель сокетов очень удобна для одновременного прослушивания нескольких процессов на одном порту и конкуренции за принятие новых соединений. Понятно, что вы могли подумать, что Apache делает это со значительным предостережением, что каждый процесс будет принимать только одно соединение, а затем умереть. Потеря эффективности для Apache заключается в накладных расходах на новые процессы и не имеет ничего общего с операциями сокета.
- Для Node.js, когда N работников конкурируют за один сокет, это чрезвычайно разумное решение. Альтернативой является создание встроенного front-end типа Nginx и передача этого прокси-трафика отдельным работникам, чередующиеся между рабочими для назначения новых подключений. Эти два решения имеют очень схожие характеристики. И поскольку, как я уже упоминал выше, вы, скорее всего, захотите иметь Nginx (или альтернативу), выходящий из вашей службы node, выбор здесь действительно между:
Общие порты: nginx (port 80) --> Node_workers x N (sharing port 3000 w/ Cluster)
против
Индивидуальные порты: nginx (port 80) --> {Node_worker (port 3000), Node_worker (port 3001), Node_worker (port 3002), Node_worker (port 3003) ...}
Вероятно, некоторые преимущества для настройки отдельных портов (возможно, имеют меньшую связь между процессами, имеют более сложные решения по балансировке нагрузки и т.д.), но определенно больше работы по настройке и встроенный модуль кластера это альтернатива с низкой сложностью, которая работает для большинства людей.
Ответ 2
Один из способов - запустить несколько экземпляров node.js на сервере, а затем поставить перед ними балансировку нагрузки (предпочтительно неблокирующую, например nginx).
Ответ 3
Райан Дал отвечает на этот вопрос в техническом разговоре, который он дал в Google прошлым летом. Перефразируя "просто запускайте несколько процессов node и используйте что-то разумное, чтобы они могли общаться, например, sendmsg() - стиль IPC или традиционный RPC".
Если вы хотите сразу же разобрать свои руки, посмотрите spark2 Forever. Это заставляет нереститься несколько node процессов тривиально легко. Он обрабатывает настройку совместного использования портов, поэтому каждый может принимать соединения с одним и тем же портом, а также автоматически обновлять, если вы хотите убедиться, что процесс перезапускается, если/когда он умирает.
ОБНОВЛЕНИЕ - 10/11/11. Консенсус в сообществе node кажется тем, что Cluster теперь является предпочтительным модулем для управления несколькими экземплярами node на машину. Forever также стоит посмотреть.
Ответ 4
Multi- node использует все ядра, которые у вас могут быть.
Посмотрите http://github.com/kriszyp/multi-node.
Для более простых нужд вы можете запустить несколько копий node на разных номерах портов и поставить перед ними балансировку нагрузки.
Ответ 5
Как упоминалось выше, Cluster будет масштабировать и балансировать ваше приложение по всем ядрам.
добавив что-то вроде
cluster.on('exit', function () {
cluster.fork();
});
Перезапустит всех неудачных работников.
В наши дни многие люди предпочитают PM2, который обрабатывает кластеризацию для вас, а также предоставляет некоторые интересные функции мониторинга.
Затем добавьте Nginx или HAProxy перед несколькими машинами, работающими с кластеризацией, и у вас есть несколько уровней отказоустойчивости и гораздо более высокая грузоподъемность.
Ответ 6
Вы можете использовать кластер. Проверьте это.
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
// Workers can share any TCP connection
// In this case its a HTTP server
http.createServer(function(req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
}
Ответ 7
Будущая версия node позволит вам развить процесс и передать ему сообщения, и Райан заявил, что хочет найти способ совместного использования файловых обработчиков, поэтому он не будет прямой реализацией Web Worker.
В настоящее время для этого нет легкого решения, но все еще очень рано, и node является одним из самых быстрорастущих проектов с открытым исходным кодом, которые я когда-либо видел, поэтому ожидаем чего-то удивительного в ближайшем будущем.
Ответ 8
Spark2 основан на Spark, который теперь больше не поддерживается. Cluster является его преемником, и у него есть некоторые интересные функции, такие как нерестование одного рабочего процесса на ядро процессора и возрождающихся мертвых работников.
Ответ 9
Я использую Node worker, чтобы запускать процессы простым способом из моего основного процесса. Кажется, он отлично работает, пока мы ждем официального пути.
Ответ 10
Новый парень в блоке здесь - LearnBoost "Вверх" .
Он обеспечивает перезагрузку с нулевым временем простоя и дополнительно создает несколько рабочих (по умолчанию количество процессоров, но настраивается), чтобы обеспечить лучшее из всех миров.
Это новый, но, похоже, довольно стабильный, и я использую его в одном из моих текущих проектов.
Ответ 11
Node Js поддерживает кластеризацию, чтобы воспользоваться всеми преимуществами вашего процессора. Если вы не используете его с кластером, возможно, вы теряете свои аппаратные возможности.
Кластеризация в Node.js позволяет создавать отдельные процессы, которые могут совместно использовать один и тот же порт сервера. Например, если мы запускаем один HTTP-сервер в Port 3000, это один сервер, работающий на одном потоке на одном ядре процессора.
Код, показанный ниже, позволяет группировать ваше приложение. Этот код является официальным кодом, представленным Node.js.
var cluster = require('cluster');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
Object.keys(cluster.workers).forEach(function(id) {
console.log("I am running with ID : " + cluster.workers[id].process.pid);
});
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
//Do further processing.
}
проверьте эту статью для полного учебника
Ответ 12
Также можно создать веб-сервис как несколько автономных серверов, которые прослушивают сокеты unix, так что вы можете передавать функции, такие как обработка данных, в отдельные процессы.
Это похоже на большинство архитектур веб-сервера scrpting/database, где процесс cgi обрабатывает бизнес-логику, а затем толкает и извлекает данные через unix-сокет в базу данных.
разница заключается в том, что обработка данных записывается как веб-сервер node, прослушивающий порт.
он более сложный, но, в конечном счете, его, где нужно многоядерное развитие. многопроцессорную архитектуру, использующую несколько компонентов для каждого веб-запроса.
Ответ 13
Можно масштабировать NodeJS до нескольких ящиков, используя чистый балансировщик нагрузки TCP (HAProxy) перед несколькими ящиками, запускающими один процесс NodeJS каждый.
Если у вас есть общие знания для совместного использования между всеми экземплярами, вы можете использовать центральный магазин Redis или аналогичный, который затем можно получить из всех экземпляров процесса (например, из всех блоков)