Главная проблема javascript это то что он однопоточный. Эта же проблема есть и в приложения написанных на NodeJS.
Итак нам понадобится:
- виртуальная машина с Windows Server 2012 или выше
 - установленная IIS
 - приложение на NodeJS (в примере будет использоваться фреймворк Express)
 - и «магия»
 
Инструкцию по установке Windows и настройке IIS описывать не буду, это можно найти в интернете. Приступаем сразу к запуску NodeJS приложения.
Краткая предыстория
Имеется проект написанный на NodeJS, которому требуется обрабатывать большие JSON файлы (около 100-200 клиентских приложений, которые передаю и принимают файлы объемом 40-80 Мб). В один момент времени может возникнуть ситуация, когда несколько пользователей одновременно сделают запрос. И в это время количество ОЗУ может не хватить (по моему по умолчанию ограничение 2 Гб). NodeJS вызовет ошибку, а IIS перезапустит пул. Можно конечно увеличить это ограничение, но рано или поздно будут возникать проблемы с производительностью.
Решение: распределение нагрузки при помощи виртуальных каталогов
Простое приложение на NodeJS
Мы будем использовать приложение, которое будет написано при помощи фреймворка express.
Файл: app.js
var express = require('express');
var app = express();
var join = require('path').join;
/*** Порт для работы приложения */
var port = normalizePort(process.env.PORT);
/*** Виртуальный каталог */
var vPath = process.env.virtualDirPath || '';
app.use(vPath + '/', express.static(join(__dirname, 'public')));
app.get(vPath + '/', function (req, res) {
    res.send(vPath);
});
app.listen(port, function () {
    console.log('Example app listening on port ' + port + '!');
});
/**
 * Normalize a port into a number, string, or false.
 * @param {any} val номер порта
 * @returns {number|boolean}
 */
function normalizePort(val) {
    var port = parseInt(val, 10);
    if (isNaN(port)) {
        // named pipe
        return val;
    }
    if (port >= 0) {
        // port number
        return port;
    }
    return false;
}
Файл: packge.json
{
  "name": "simple-express",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "dependencies": {
    "args-parser": "^1.1.0",
    "express": "^4.17.1"
  },
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
Файл: web.config
<configuration>
  <system.webServer>
    <handlers>
      <add name="iisnode" path="app.js" verb="" modules="iisnode" />     
    </handlers> 
    <rewrite> 
      <rules> 
        <rule name="myapp"> 
          <match url="/" />
          <action type="Rewrite" url="app.js" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>
Располагаем наше приложение в корневом каталоге IIS (можно расположить, где угодно, но нужно будет дополнительно настраивать). У меня оно называется arm

Настройка IIS
Примечание: NodeJS приложению требуются дополнительные права на исполнение, для этого нужно убедиться, что есть полный доступ для пользователя IIS_IUSRS

Далее создаем столько пулов на сколько потоков мы хотим «разделить» наше приложение. В моем примере это будет 2.
При создании пулов не требуется исполнение CLR, нам нужен сам факт наличия, т.к. пул IIS нам и обеспечивает параллельность выполнения.


После создания пулов переходим к настройки виртуальных каталогов. Для этого в приложении по умолчанию «Default Web Site» выбираем «Добавить виртуальный каталог»

- в «псевдониме» указываем наименование приложения. Я указывал arm, arm2
 - «физический путь» указывает на каталог wwwroot/arm
 - после создания требуется преобразовать в приложение и указать соответствующий пул
 



Последним «штрихом» является web.config на уровне корневого каталога
<configuration>
  <location path="arm">
    <appSettings>
      <add key="virtualDirPath" value="/arm" />
    </appSettings>
  </location>
  <location path="arm2">
    <appSettings>
      <add key="virtualDirPath" value="/arm2" />
    </appSettings>
  </location>
</configuration>
virtualDirPath — дополнительная настройка, которая используется в приложении на NodeJS
... var vPath = process.env.virtualDirPath || ''; app.use(vPath + '/', express.static(join(__dirname, 'public'))); ...

Примечание: особенность настройки заключается в том, что физически в файловой системе у нас будет храниться один каталог с приложением, но IIS при помощи «виртуализации» создаст несколько
Результат

Ниже мы видим как IIS под каждый экземпляр виртуального каталога создала отдельный процесс
