【问题标题】:is it possible to make nodejs scripts listen to same port是否可以让 nodejs 脚本监听相同的端口
【发布时间】:2014-01-18 07:44:29
【问题描述】:

我在另一个帖子里问了同样的问题,但答案误解了我的问题,所以我再问一次

我有两个脚本

 s1.js, s2.js

都使用 express 框架并监听特定的端口。

我打电话

node s1.js //listens to port 8080

node s2.js //listens to port 8081

启动两个脚本,一个监听 8080 端口,另一个监听 8081 端口。

是否可以让 nodejs 脚本监听同一个端口 8080? 调用时如何分隔两个脚本

www.abc.com:8080

欢迎评论

更新问题

我尝试代码 app.js

  var express = require("express");
  var app = express();

  app.use('/app1', require( './app1/index.js').app);
  app.use('/app2', require( './app2/index.js').app);

  app.listen(8081);

在路径 ./app1/index.js

  var express = require("express");
  var app = express();
  console.log("app1");
  app.listen(8081);

在路径 ./app2/index.js

  var express = require("express");
  var app = express();
  console.log("app2");
  app.listen(8081);

然后我打电话给

  node app

控制台报错:

app1

/Users/myname/node_modules/express/lib/application.js:111
  if (fn.handle && fn.set) app = fn;
        ^
TypeError: Cannot read property 'handle' of undefined
    at Function.app.use (/Users/zhengwang/node_modules/express/lib/application.js:111:9)
    at Object.<anonymous> (/Users/zhengwang/multi.js:27:7)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:901:3

【问题讨论】:

  • 如果可能,他们中的哪一个会处理响应?
  • 你的意思是不同的nodejs脚本必须监听不同的端口,这是必须的吗?
  • 对于 php,www.abc.com/s1.php www.abc.com/s2.php 监听相同的端口。
  • @freakish 太棒了!听起来您很了解该主题,为什么不将其发布为答案?

标签: node.js


【解决方案1】:

Cluster 执行此操作,Express.vhost 也执行此操作。实际上,您可以同时使用两者,并且只使用 1 个端口。

// server.js
var cluster = require('cluster');
var express = require('express');
var app = express ();

var cpus = require('os').cpus().length - 1;

if(cluster.isMaster) {
    for(var i=0;i<cpus;i++) {
        cluster.fork ();
    }
}
else {
    app
        .use( express.vhost('www.site1.com'), require('./site1.js').app ) )
        .use( express.vhost('www.site2.com'), require('./site2.js').app ) )
        .listen(8080);
}

在 site1.js 和 site2.js 中,您可以像编写任何其他节点应用程序一样将它们写出来,除了两个小东西。导出您的应用程序 (var app = exports.app = express() ),并且不要在这两个文件中监听 (app.listen(8080))。您可以看到 server.js 已经为您进行了监听,并且还需要从中导出两个“应用程序”。现在,您在同一台服务器上的所有站点都可以在同一端口上运行,并且可以在服务器拥有的每个 CPU 上运行。我确实相信您的服务器本身也需要为多个虚拟主机正确设置,但这超出了所问的问题。

Cluster 处理将请求发送到正在运行的节点应用程序 (server.js) 之一,然后 express 处理根据使用的 url 为请求使用正确的应用程序 (site1.js、site2.js)。我会说非常简单。我很喜欢节点。

【讨论】:

  • 我没有为您编写代码,请查看 cluster 和 express.vhost 如何使其适应您的需求。
  • @Chris 我真的很喜欢你在最后一段中的总结;很有帮助。
【解决方案2】:

好吧,事实是这样:多个进程可以监听同一个端口。我知道有两种情况(仅在 POSIX 上):

1) 分叉。当一个主进程监听一个套接字然后它自己分叉时,所有子进程都在同一个套接字上监听。这意味着多个进程侦听同一个套接字。这实际上是Node.js cluster 所做的。你可能想看看它。

2) 在两个独立进程之间传递套接字文件描述符。是的,这是可以做到的。然而,这涉及到很多工作。基本上两个进程通过 UDS 进行通信,其中一个将套接字文件描述符传递给另一个,因此另一个也可以监听它。然而,这需要一些低级的网络编程(传递套接字的 FD 并不像传递消息那样简单)。以下是 C 中此类实现的示例:

http://lists.canonical.org/pipermail/kragen-hacks/2002-January/000292.html

我不确定是否可以使用 Node.js 完成 2)。

请注意,在这两种情况下,进程之间的负载平衡取决于操作系统(操作系统决定哪个进程处理套接字上的accept 和/或recv)。据我所知,大多数操作系统都做得很好。

然而这实在是不切实际。我从未见过解决方案 2)在现实生活中使用(极其复杂,一些严重的安全问题),至于解决方案 1)它被(例如)Apache Web 服务器广泛使用,但现在人们倾向于使用线程和/或异步系统因此分叉变得有点过时(除非您想充分利用多个 CPU 内核 - Node.js 中没有线程)。

所以在你的情况下,我想最简单的解决方案是在两台服务器前面放置一个(ha)代理,以便在这两个脚本之间进行负载平衡。

请注意,这个问题很奇怪。您说您有两个不同的服务器,但您希望它们在同一个端口上侦听。这意味着每个请求都将发送给其中一个。特别是一半用户将由s1 处理,而另一半由s2 处理。如果他们做同样的事情,为什么会有两个文件?如果他们正在做其他事情,那么为什么一半的用户会得到不同的结果?看来您正在尝试做一些真的很糟糕的事情。

【讨论】:

  • Windows 中的内核允许多个应用程序共享一个端口,只要 URL 是唯一的。
  • @WiredPrairie 我不明白。 URL 与端口共享有何关系? URL 是一个 HTTP 协议,它不在内核中。另一方面,我对 Windows 的魔力了解不多。
  • @WiredPrairie 啊,我明白了。非常有趣,谢谢。我应该提到我只是在谈论 POSIX。
  • @freakish cluster 实际上也传递 fd(通过 Unix 域套接字,顺便说一下,这与 UDP 不同),在 POSIX (/UNIX) 上也可以有多个只要绑定到的 主机名 是唯一的,进程就在同一端口上侦听。
  • @freakish 解释了in the fine manual :)
【解决方案3】:

你的 /app1/index.js 和 /app2/index.js 不应该 listen(),因为 app.js 已经在监听了,它们都需要导出 app 对象。

var express = require("express");
var app = exports.app = express();
console.log("app1");

app2/index.js 同上

var express = require("express");
var app = exports.app = express();
console.log("app2");

【讨论】:

  • 如果端口是80,想知道如何访问不同路径(app1,app2)中的index.js
  • 没有理由访问它...每个站点的所有代码都进入这两个应用程序(app1/index.js 和 app2/index.js)所有你的 app.get() 和应用程序。 post() 进去。
  • 对于php,www.abc.com/app1.php www.abc.com/app2.php都是正常的,这是我希望nodejs脚本能做到的
  • 如果这就是你想要做的,那么这就是矫枉过正。
猜你喜欢
  • 2014-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-27
  • 2020-07-18
  • 2018-10-29
  • 2012-12-29
相关资源
最近更新 更多