在多个node.js HTTP进程之间共享一个端口

时间:2012-05-28 23:03:06

标签: linux node.js http vhosts

我有一个root服务器,上面运行着几个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设置为其父文件夹(someProjectanotherProject等)。

想想ov vHosts。每个项目都会启动一个侦听自己域名的Web服务器。而且存在问题。只有一个脚本可以启动,因为它们都尝试绑定到端口80.我深入研究了node.js API并寻找可能的解决方案:child_process.fork()

可悲的是,这并不是很好。当我尝试将服务器实例发送到主进程(以便稍后发出请求)或从主服务器向salve发送requestresponse的对象时,我得到错误。这是因为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);
  }
});

这里孩子直接听主人的服务器。所以中间没有域检查。所以这是一个死胡同。

我也考虑过Cluster,但是它使用与句柄相同的技术,因此具有相同的限制。

所以...有什么好主意吗?

我目前所做的是相当黑客攻击。我做了一个名为distroy的软件包。它绑定到端口80,并在内部代理所有对Unix域套接字路径的请求,如/tmp/distroy/http/www.example.com,单独的应用程序监听这些路径。这也(有点)适用于HTTPS(请参阅我在SNI上的问题)。 剩下的问题是,原始IP地址丢失了,因为它现在总是127.0.0.1。我想我可以通过monkeypatching net.Server来避免这种情况,这样我就可以在打开连接之前传输IP地址。

3 个答案:

答案 0 :(得分:9)

如果您对node.js解决方案感兴趣,请查看bouncy,node.js中支持websocket和https的http路由器代理/负载均衡器。

定义您的routes.json,如

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

然后使用

运行弹性
 bouncy routes.json 80

答案 1 :(得分:1)

就个人而言,我只是让他们全部听专用端口或最好是套接字,然后将所有东西都放在专用的路由器脚本或nginx之后。这是IMO最简单的方法。

答案 2 :(得分:0)

对于连接中间件,有vhost扩展名。也许你可以复制他们的一些概念。