Совместное использование одного порта несколькими HTTP-процессами node.js

У меня есть корневой сервер с несколькими проектами node.js. Предполагается, что они работают отдельно в своих собственных процессах и каталогах. Рассмотрим следующую файловую структуру:

/home
+-- /node
    +-- /someProject      | www.some-project.com
    |   +-- index.js
    |   +-- anotherFile.img
    |   +-- ...
    +-- /anotherProject   | www.another-project.com
    |   +-- /stuff
    |   +-- index.js
    |   +-- ...
    +-- /myWebsite        | www.my-website.com
    |   +-- /static
    |   +-- index.js
    |   +-- ...
    +-- ...               | ...

Каждый index.js должен запускаться как отдельный процесс с его cwd, установленным в его родительскую папку ( someProject, otherProject, и т.д.).

Подумайте о vHosts. Каждый проект запускает веб-сервер, который слушает в своем собственном домене. И есть проблема.Только один скрипт может запуститься, так как все они пытаются привязаться к порту 80. Я копался в API node.js и искал возможное решение:child_process.fork().

К сожалению, это не очень хорошо работает. Когда я пытаюсь отправить экземпляр сервера главному процессу (для отправки запроса позже) или объект, состоящий из запроса и ответа от главного процесса к подчиненному, я получаю ошибки. Это связано с тем, что node.js внутренне пытается преобразовать эти расширенные объекты в строку JSON, а затем повторно преобразует их в исходную форму. Это приводит к тому, что все объекты теряют свою ссылку и функциональность.

Второй подходchild.js

var http = require("http");

var server = http.createServer(function(req, res) {
    // stuff...
});
server.listen(80);

process.send(server); // Nope

Первый подходmaster.js

var http = require("http"),
    cp = require("child_process");

var child = cp.fork("/home/node/someProject/index.js", [], { env: "/home/node/someProject" });

var router = http.createServer(function(req, res) {
    // domaincheck, etc...
    child.send({ request: req, response: res }); // Nope
});
router.listen(80);

Итак, это тупик. Но эй! Node.js предлагает своего рода дескрипторы, которые можно отправлять. Вот пример из документации:

master.js

var server = require('net').createServer();
var child = require('child_process').fork(__dirname + '/child.js');
// Open up the server object and send the handle.
server.listen(1337, function() {
  child.send({ server: true }, server._handle);
});

child.js

process.on('message', function(m, serverHandle) {
  if (serverHandle) {
    var server = require('net').createServer();
    server.listen(serverHandle);
  }
});

Здесь дочерний процесс напрямую слушает главный сервер. Таким образом, между ними нет проверки домена. Так что здесь тупик.

Я также думал оКластере, но он использует ту же технологию, что и дескриптор, и поэтому имеет те же ограничения.

Итак... есть хорошие идеи?

То, чем я сейчас занимаюсь, довольно хакерское. Я сделал пакет под названием distroy. Он привязывается к порту 80 и внутренне проксирует все запросы к путям сокетов домена Unix, таким как /tmp/distroy/http/www.example.com, которые прослушивают отдельные приложения. Это также (вроде бы) работает для HTTPS (см. мой вопрос о SNI). Оставшаяся проблема заключается в том, что исходный IP-адрес потерян, так как теперь он всегда 127.0.0.1.Я думаю, что могу обойти это, пропатчив net.Server, чтобы я мог передавать IP-адрес перед открытием соединения.

15
задан Community 23 May 2017 в 12:14
поделиться