在多个node.js HTTP进程之间共享一个端口 [英] Sharing one port among multiple node.js HTTP processes
问题描述
我有一个运行有多个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屋!