在多个node.js HTTP进程之间共享一个端口 [英] Sharing one port among multiple node.js HTTP processes

查看:1369
本文介绍了在多个node.js HTTP进程之间共享一个端口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个运行有多个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 anotherProject 等)。



Think ov vHosts。每个项目都会启动一个监听自己域名的网络服务器。而且存在问题。只有一个脚本可以启动,因为它们都尝试绑定到端口80.我深入研究了node.js API并寻找可能的解决方案: 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(服务器); //不是

第一种方法 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等...
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');
//打开服务器对象并发送句柄。
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);
}
});

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



我还想过 群集 ,但这使用与句柄相同的技术,因此具有相同的限制。



<那么......有什么好主意吗?



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

解决方案

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


I have a root server running with several node.js projects on it. They are supposed to run separately in their own processes and directories. Consider this file structure:

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

Each index.js should be started as an individual process with its cwd set to its parent-folder (someProject, anotherProject, etc.).

Think ov vHosts. Each project starts a webserver which listens on its own domain. And there's the problem. Only one script can start since, they all try to bind to port 80. I digged to into the node.js API and looked for a possible solution: child_process.fork().

Sadly this doesn't work very well. When I try to send a server instance to the master process (to emit a request later on) or an object consiting of request and response from the master to the salve I get errors. This is because node.js internally tries to convert these advanced objects to a JSON string and then reconverts it to its original form. This makes all the objects loose their reference and functionality.

Seccond approach child.js

var http = require("http");

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

process.send(server); // Nope

First approach 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);

So this is a dead end. But, hey! Node.js offers some kind of handles, which are sendable. Here's an example from the documentation:

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

Here the child directly listens to the master's server. So there is no domaincheck inbetween. So here's a dead end to.

I also thought about Cluster, but this uses the same technology as the handle and therefore has the same limitations.

So... are there any good ideas?

What I currently do is rather hack-ish. I've made a package called distroy. It binds to port 80 and internally proxies all requests to Unix domain socket paths like /tmp/distroy/http/www.example.com, on which the seperate apps listen. This also (kinda) works for HTTPS (see my question on SNI). The remaining problem is, that the original IP address is lost, as it's now always 127.0.0.1. I think I can circumvent this by monkeypatching the net.Server so that I can transmit the IP address before opening the connection.

解决方案

Personally, I'd just have them all listen on dedicated ports or preferably sockets and then stick everything behind either a dedicated router script or nginx. It's the simplest approach IMO.

这篇关于在多个node.js HTTP进程之间共享一个端口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆