У меня есть корневой сервер с несколькими проектами 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-адрес перед открытием соединения.