[ Ця публікація оновлена станом на 2012-09-02 (новіше, ніж вище). ]
Node.js абсолютно має масштаб на багатоядерних машинах.
Так, Node.js - це один потік на процес. Це дуже обдумане дизайнерське рішення і позбавляє від необхідності розібратися з фіксацією семантики. Якщо ви не згодні з цим, ви, мабуть, ще не усвідомлюєте, наскільки шалено важко налагоджувати багатопотоковий код. Для більш глибокого пояснення моделі процесу Node.js і чому вона працює таким чином (і чому вона НІКОЛИ не підтримуватиме декілька потоків) читайте в іншому моєму дописі .
Тож як я можу скористатися своєю 16 ядерною коробкою?
Два способи:
- Для великих важких завдань обчислення, таких як кодування зображень, Node.js може запускати дочірні процеси або надсилати повідомлення додатковим робочим процесам. У цьому дизайні ви мали б один потік, який керує потоком подій та N процесів, виконуючи важкі обчислювальні завдання та пережовуючи інші 15 процесорів.
- Для масштабування пропускної здатності у веб-службі слід запустити кілька серверів Node.js в одному вікні, по одному на ядро та розділити трафік запиту між ними. Це забезпечує чудову спорідненість з процесором і дозволить масштабувати пропускну здатність майже лінійно з кількістю ядер.
Пропускна здатність масштабування на веб-сервісі
Оскільки v6.0.X Node.js включив модуль кластера прямо з вікна, що спрощує налаштування декількох працівників вузлів, які можуть слухати на одному порту. Зауважте, що це НЕ те саме, що і старший модуль "кластерного" навчання, доступний через 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) ...}
Можливо, є певні переваги в налаштуванні окремих портів (можливо, менше зв'язок між процесами, більш складні рішення щодо балансування навантаження тощо), але це, безумовно, більше роботи над налаштуванням, і вбудований кластерний модуль низький -складність альтернатива, яка працює для більшості людей.