2012-05-28 18 views
15

Tengo un servidor raíz ejecutándose con varios proyectos node.js en él. Se supone que se ejecutan por separado en sus propios procesos y directorios. Considere esta estructura de archivos:Compartiendo un puerto entre múltiples procesos node.js HTTP

/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 
    | +-- ... 
    +-- ...    | ... 

Cada index.js deben iniciarse como un proceso individual con su cwd conjunto a su padre-carpeta (someProject, anotherProject, etc.).

Think ov vHosts. Cada proyecto inicia un servidor web que escucha en su propio dominio. Y ahí está el problema. Solo una secuencia de comandos puede comenzar, ya que todos intentan enlazarse al puerto 80. Indagué en la API node.js y busqué una posible solución: child_process.fork().

Lamentablemente, esto no funciona muy bien. Cuando trato de enviar una instancia de servidor al proceso maestro (para emitir una solicitud más tarde) o un objeto que conste de request y response del maestro al bálsamo recibo errores. Esto se debe a que node.js intenta internamente convertir estos objetos avanzados a una cadena JSON y luego los reconvierte a su forma original. Esto hace que todos los objetos pierdan su referencia y funcionalidad.

enfoque seccond child.js

var http = require("http"); 

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

process.send(server); // Nope 

Primera aproximación 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); 

Así que este es un callejón sin salida. ¡Pero hey! Node.js ofrece algún tipo de identificadores, que se pueden enviar. He aquí un ejemplo de la documentación:

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); 
    } 
}); 

Aquí el niño escucha directamente al servidor del maestro. Entonces no hay un chequeo de dominio entre ellos. Así que aquí hay un callejón sin salida para.

También pensé en Cluster, pero esto usa la misma tecnología que el mango y por lo tanto tiene las mismas limitaciones.

Entonces ... ¿hay alguna buena idea?

Lo que hago actualmente es bastante hack-ish. He hecho un paquete llamado distroy. Se une al puerto 80 y envía un proxy interno de todas las solicitudes a las rutas de socket de dominio de Unix como /tmp/distroy/http/www.example.com, en las cuales las diferentes aplicaciones escuchan. Esto también (algo así) funciona para HTTPS (vea mi pregunta en SNI). El problema restante es que se pierde la dirección IP original, ya que ahora siempre es 127.0.0.1. Creo que puedo eludir esto pacando el net.Server para que pueda transmitir la dirección IP antes de abrir la conexión.

+1

Si a alguien se le ocurre una solución de "mejor ajuste" para este problema, marcaré su respuesta como la correcta. – buschtoens

+0

Actualmente estoy trabajando en algo que debería resolver este problema ... – buschtoens

+0

¿Alguien sabe cómo hacer esto mientras ejecuta un nodo dentro de IIS? –

Respuesta

1

Personalmente, me gustaría que todos escuchen en puertos dedicados o, preferiblemente, sockets y luego guarden todo detrás de un script de enrutador dedicado o nginx. Es el enfoque más simple de IMO.

+0

Simplemente me gusta la idea de tener un ligero node.js-script que reescribe internamente la solicitud. Pero lamentablemente esto es imposible en este momento y tengo que seguir con los enchufes de Unix. – buschtoens

+1

Estoy realmente confundido sobre por qué mi respuesta es 0/2 cuando la recomendación de almypal es exactamente la misma (simplemente deja todo en puertos diferentes y usa un enrutador diferente) y va a 6/0. Realmente no me importa un nivel profundo, pero es curioso. – Chuck

9

Si está interesado en una solución node.js consulte bouncy, un websocket y https-capable http enrutador proxy/load balancecer en node.js.

definir su routes.json como

{ 
     "beep.example.com" : 8000, 
     "boop.example.com" : 8001 
} 

y luego ejecutar saltos utilizando

bouncy routes.json 80 
+0

hinchable es casi lo mismo que [http-proxy] (https://github.com/nodejitsu/node-http-proxy). Lo que me molesta de este tipo de solución es el hecho de que el servidor del proyecto se une a otro puerto, que en realidad no utiliza, ya que debe vincularse al puerto 80. – buschtoens

+0

+1 en http-proxy - eso es lo que uso – bryanmac

0

para el middleware de conexión existe vhost extensión. Tal vez podrías copiar algunos de sus conceptos.

+0

Connect's 'vhost' bascialmente hace esto:' server.emit ('request', req, res); '. Ya lo intenté. Tendrá que obtener la instancia del servidor del proceso secundario para poder emitir eventos en él. Como node.js internamente codifica esta instancia, toda la referencia se pierde y no puedo emitir eventos allí. – buschtoens

Cuestiones relacionadas