使用Node.js Express托管多个网站

10

我在配置两个不同域名的Node.js应用程序时遇到了问题。有两个目录。

"/abc/" -> express-admin setup (backend) -> admin.abc.com

并且

"/xyz/" -> express setup (frontend) -> abc.com

我需要将admin.abc.com指向express-admin的设置,并将abc.com指向express的设置。我已安装vhost并且两个站点都侦听端口80。

已添加

app.use(vhost('abc.com', app)); // xyz/app.js file
app.use(vhost('admin.abc.com', app)); // abc/app.js file

我的问题:

  • forever 已安装,但每次我启动两个应用程序时,第二个应用程序总是会停止。尝试使用不同的端口来运行这两个应用程序,但仍然出现相同的错误。单独运行它们没有问题。

  • 我认为我的设置对于域名转发来说太复杂了。有更好的建议吗?也许我可以使用一个主 app.js 文件来将域路由到它们各自的应用程序,而不是使用每个应用程序的 app.js。


3
当第二个应用程序启动时,您仍在使用相同的端口和相同的网络接口来托管应用程序。因此,它始终会发现该端口正在使用中。即使使用虚拟主机,您也应该使用不同的端口来托管,参见此示例了解详情。也许您最好使用node-http-proxy,使应用程序完全独立?请参见 此文章 进行比较。 - veggiesaurus
谢谢@veggiesaurus,node-http-proxy应该是正确的选择。我会告诉你进展如何。 - Pradino
请放心。我已经添加了更详细的答案,以防其他人遇到同样的问题。 - veggiesaurus
请考虑使用 Nginx - 一种在单个服务器内启动多个 Node 服务器的良好解决方案:https://dev59.com/o2445IYBdhLWcg3wKHAJ - Oleg
4个回答

9

我不确定您如何使用虚拟主机。首先,在使用虚拟主机的方法中,您只需要运行一个express应用程序,而不是两个。以下是一个示例。

var express = require('express');
var vhost = require('vhost');

/*
edit /etc/hosts:

127.0.0.1       api.mydomain.local
127.0.0.1       admin.mydomain.local
*/

// require your first app here

var app1 = require("./app1");

// require your second app here

var app2 = require("./app2");

// redirect.use(function(req, res){
//   if (!module.parent) console.log(req.vhost);
//   res.redirect('http://example.com:3000/' + req.vhost[0]);
// });

// Vhost app

var appWithVhost = module.exports = express();

appWithVhost.use(vhost('api.mydomain.local', app1)); // Serves first app

appWithVhost.use(vhost('admin.mydomain.local', app2)); // Serves second app

/* istanbul ignore next */
if (!module.parent) {
  appWithVhost.listen(8000);
  console.log('Express started on port 8000');
}

您只需使用forever运行启用了vhost的主要express应用程序。


1
如果使用相同的设置来运行更多(比如20个)的Express应用程序,是否会出现性能问题或其他问题? 假设其中19个非常轻量级(使用Express渲染简单的Jade模板),但第20个则稍微复杂一些,需要更多的CPU。如果每个站点都有10个活跃用户,那么查看较复杂站点的10个用户是否会导致其他19个站点的观众出现减速? - Good Idea
@标准质量。vhost的问题在于所有这些独立的应用程序都在同一个用户空间中运行。也就是说,可能需要在单独的空间中运行它们(例如Apache中的suexec),以便如果一个站点被黑客攻击/崩溃,它不能感染其他站点。但在这个例子中可能并不重要。请查看pm2:http://pm2.keymetrics.io/docs/usage/startup/#user-permissions - cmroanirgo

7
您正在同一端口上托管应用程序,使用相同的网络接口。因此,当第二个应用程序启动时,它将始终找到已使用的端口。如果您想在同一端口上使用多个应用程序,则每个应用程序都需要拥有自己的网络接口。使用虚拟主机时,仍需要为每个应用程序监听不同的端口。有关详细信息,请参见此示例。如果您希望您的应用程序完全独立,最好使用node-http-proxy。这允许您在端口80上托管代理,将请求转发到侦听不同端口的express应用程序。如果其中一个应用程序崩溃,它将不会崩溃另一个应用程序,这与虚拟主机方法不同。 此文章提供了使用node-http-proxy实现的示例。

7

感谢 @veggiesaurus 指出 node-http-proxy。抱歉发布晚了。

以下是我如何使用 node-http-proxy 解决问题的方法:

文件夹结构:

  • www/
    • server.js
    • abc/ [express 设置]
      • app.js
    • xyz/ [express-admin 设置]
      • node_modules/express-admin/app.js

"abc" 和 "xyz" 分别有它们自己的设置,并在端口 x.x.x.x:3001 和 x.x.x.y:3002 上运行。

我安装了 node-http-proxy 并添加了 server.js 文件,其中包含以下代码。参考了这个 链接

var http = require('http');
var httpProxy = require('http-proxy');

var proxy = httpProxy.createProxy();
var options = {  
  'abc.com': 'http://x.x.x.x:3001',
  'xyz.com': 'http://x.x.x.y:3002'
}

http.createServer(function(req, res) {
  proxy.web(req, res, {
    target: options[req.headers.host]
  });
}).listen(80);

最后,使用forever运行所有3个应用程序的设置,以在端口3001、3002和80上永久运行。

0
const express = require("express");
const app = express();
const fs = require('fs');
app.use((req, res, next) => {
    let reqDomain = req.get("host");
    if (reqDomain.indexOf(":") > -1) {
        reqDomain = reqDomain.split(":")[0];
    }
    if(reqDomain.endsWith(".local")) {
        reqDomain = reqDomain.substring(0, reqDomain.length - 6);
    }
    const domainPath = "public/" + reqDomain;
    let filePath = domainPath + req.originalUrl;
    filePath = fs.lstatSync(filePath).isDirectory() ? filePath + "/index.html" : filePath;
    console.log(__dirname + "/" + filePath);
    res.sendFile(filePath, { root: __dirname });
});
const port = process.env.PORT || 80;
app.listen(port, () => console.log("Server Started on Port " + port));

public 目录下放置像 'my-first-website.com'、'my-second-website.com' 这样的文件夹。

为了本地测试,在 /etc/hosts 中添加以下内容。

127.0.0.1 my-first-website.com.local
127.0.0.1 my-second-website.com.local

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接