Ich habe einen Root-Server, auf dem mehrere node.js-Projekte laufen. Sie sollen separat in ihren eigenen Prozessen und Verzeichnissen laufen. Betrachten Sie diese Dateistruktur:Einen Port unter mehreren node.js-HTTP-Prozessen teilen
/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
| +-- ...
+-- ... | ...
Jeder index.js als individueller Prozess mit seinem cwd
Satz zu seinem übergeordneten Ordner gestartet werden soll (someProject
, anotherProject
, etc.).
Denken Sie an vHosts. Jedes Projekt startet einen Webserver, der auf seine eigene Domain hört. Und da ist das Problem. Nur ein Skript kann starten, da alle versuchen, an Port 80 zu binden. Ich habe in die node.js-API gegraben und nach einer möglichen Lösung gesucht: child_process.fork()
.
Leider funktioniert das nicht sehr gut. Wenn ich versuche, eine Server-Instanz an den Master-Prozess zu senden (um später eine Anfrage zu senden) oder ein Objekt, bestehend aus request
und response
vom Master zum salve bekomme ich Fehler. Dies liegt daran, dass node.js intern versucht, diese erweiterten Objekte in eine JSON-Zeichenfolge zu konvertieren und sie dann in ihre ursprüngliche Form zurückkonvertiert. Dadurch verlieren alle Objekte ihren Bezug und ihre Funktionalität.
seccond Ansatz child.js
var http = require("http");
var server = http.createServer(function(req, res) {
// stuff...
});
server.listen(80);
process.send(server); // Nope
Erster Ansatz 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);
Also das ist eine Sackgasse. Aber hey! Node.js bietet einige Arten von Handles, die sendbar sind. Hier ist ein Beispiel aus der Dokumentation:
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);
}
});
hier direkt das Kind auf den Master-Server lauscht. Es gibt also keinen Domänencheck dazwischen. Also, hier ist eine Sackgasse.
Ich dachte auch über Cluster
, aber das verwendet die gleiche Technologie wie der Griff und hat daher die gleichen Einschränkungen.
Also ... gibt es irgendwelche guten Ideen?
Was ich derzeit mache ist eher hack-ish. Ich habe ein Paket namens distroy gemacht. Es bindet an Port 80 und proxifiziert intern alle Anfragen an Unix-Domain-Socket-Pfade wie /tmp/distroy/http/www.example.com
, auf denen die einzelnen Apps zuhören. Dies funktioniert auch (irgendwie) für HTTPS (siehe meine Frage auf SNI). Das verbleibende Problem ist, dass die ursprüngliche IP-Adresse verloren geht, da es jetzt immer 127.0.0.1 ist. Ich denke, ich kann das umgehen, indem ich die net.Server
monkeypatching, so dass ich die IP-Adresse vor dem Öffnen der Verbindung übertragen kann.
Wenn jemand eine "besser passende" Lösung für dieses Problem findet, werde ich seine Antwort als die richtige markieren. – buschtoens
Ich arbeite derzeit an etwas, das dieses Problem lösen sollte ... – buschtoens
Jeder weiß, wie dies beim Ausführen von Knoten innerhalb von IIS zu tun? –