Поскольку все мы знаем, что node.js — это однопоточное приложение, по сравнению с ним традиционный веб-сервер использует несколько потоков, чтобы использовать максимальную вычислительную мощность сервера и использовать все доступные процессоры и память.

Однако один процесс Node.js не может этого сделать (у него ограничение памяти 1 ГБ). Не думайте, что это недостаток. Позвольте мне показать вам, как просто масштабировать приложение Node.js.

Модуль кластера

В Node.js модуль кластера — это простейший шаблон для распределения нагрузки. Он автоматически разветвляет новые экземпляры приложения и распределяет по ним входящее соединение, как показано здесь на рисунке:

Главный процесс отвечает за создание ряда процессов (воркеров), каждый из которых представляет экземпляр приложения, которое мы хотим масштабировать. Затем каждое входящее соединение распределяется между клонированными рабочими процессами, распределяя нагрузку между ними.

Процесс Mater использует циклический алгоритм балансировки нагрузки, который включен по умолчанию (кроме Windows). Достаточно теории, чтобы код.

Создание простого HTTP-сервера

ClusteredApp.js

const cluster = require('cluster');
const os = require('os'); 
if(cluster.isMaster) {  
  //start as many children as the number of CPUs
  let cpus = os.cpus().length;
  for (let i = 0; i < cpus; i++){
    cluster.fork();
  }
}
else{
  require('./app.js');
}

app.js

const http = require('http'); 
const pid = process.pid; 
http.createServer((req, res) => {  
  //just to use some time in app 
  for(let i = 1e7; i > 0; i--) {}
  
  console.log('Handling request from pid:' + pid);  
  res.end('Hello from ' + pid + '\n');
}).listen(8080,() => {  
     console.log('Started ' + pid); 
});

cmd запустить «узел clusteredApp.js»

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

Например, в системе с 8 процессорами терминал должен выглядеть так: Started 14107
Started 14099
Started 14102
Started 14101
Started 14125
Started 14126< br /> Начато 14128
Начато 14189

перейдите по URL-адресу http://localhost:8080, мы увидим, что pid используется для каждого запроса рабочими процессами.

Проанализируем происходящее:

Когда мы запускаем clusteredApp из командной строки, мы фактически выполняем главный процесс. Для переменной cluster.isMaster установлено значение true, и единственная работа, которую нам нужно сделать, — это разветвить текущий процесс с помощью cluster.fork(). Мы запускаем столько воркеров, сколько процессоров в системе, чтобы использовать всю доступную вычислительную мощность.

Когда cluster.fork() выполняется из основного процесса, текущий основной модуль (clusteredApp) запускается снова, но на этот раз в рабочем режиме (для параметра cluster.isWorker установлено значение true, а для cluster.isMaster — значение false). Когда приложение работает как рабочий, оно может начать выполнять некоторую реальную работу. В нашем примере мы загружаем модуль приложения, который фактически запускает новый HTTP-сервер.