[ Это сообщение актуально по состоянию на 2012-09-02 (новее, чем указано выше). ]
Node.js действительно масштабируется на многоядерных машинах.
Да, Node.js - один поток на процесс. Это очень обдуманное проектное решение, устраняющее необходимость иметь дело с семантикой блокировки. Если вы не согласны с этим, вы, вероятно, еще не понимаете, насколько безумно сложно отлаживать многопоточный код. Для более глубокого объяснения модели процесса Node.js и почему она работает таким образом (и почему она НИКОГДА не будет поддерживать несколько потоков), прочитайте мой другой пост .
Итак, как мне воспользоваться преимуществами моего 16-ядерного блока?
Два пути:
- Для больших сложных вычислительных задач, таких как кодирование изображений, Node.js может запускать дочерние процессы или отправлять сообщения дополнительным рабочим процессам. В этом проекте у вас был бы один поток, управляющий потоком событий, а N процессов, выполняющих сложные вычислительные задачи и пережевывающих остальные 15 процессоров.
- Для масштабирования пропускной способности на веб-сервисе вы должны запустить несколько серверов Node.js на одном компьютере, по одному на ядро, и разделить трафик между ними. Это обеспечивает отличную привязку к процессору и масштабирует пропускную способность почти линейно с количеством ядер.
Масштабирование пропускной способности на веб-сервисе
Начиная с версии 6.0.X Node.js включил модуль кластера прямо из коробки, что упрощает настройку нескольких рабочих узлов, которые могут прослушивать один порт. Обратите внимание, что это НЕ то же самое, что более старый модуль "cluster" learnboost, доступный через 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 работников, конкурирующих в одном сокете, является чрезвычайно разумным решением. Альтернативой является настройка встроенного внешнего интерфейса, такого как Nginx, и передача этого прокси-трафика отдельным работникам, чередуя работников для назначения новых соединений. Два решения имеют очень похожие характеристики производительности. И поскольку, как я упоминал выше, вы, вероятно, захотите, чтобы Nginx (или его альтернатива) в любом случае стоял перед вашим сервисом узлов, выбор здесь действительно один:
Общие порты: 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) ...}
Возможно, есть некоторые преимущества в настройке отдельных портов (возможно меньшая связь между процессами, более сложные решения по распределению нагрузки и т. Д.), Но это определенно больше работы для настройки, а встроенный модуль кластера требует мало -сложная альтернатива, которая работает для большинства людей.