如何在具有不同域的同一IP /服务器上托管多个Node.js站点?

时间:2013-10-08 17:40:17

标签: node.js

我有一台绑定了一个IP的Linux服务器。我希望在此IP服务器上托管多个Node.js站点,每个站点(显然)都有一个唯一的域或子域。我希望他们都在80端口。

我有什么选择呢?

一个明显的解决方案似乎是让一个node.js网络应用程序服务的所有域都充当代理,然后传递给在唯一端口上运行的其他node.js应用程序。

13 个答案:

答案 0 :(得分:70)

选择以下其中一项:

  • 使用其他服务器(like nginx)作为反向代理。
  • 使用node-http-proxy作为反向代理。
  • 如果可以从同一个Connect / Express代码库和node.js实例提供每个域,请使用vhost middleware

答案 1 :(得分:43)

Diet.js 使用相同的服务器实例托管多个域的方式非常简单明了。您只需为每个域调用一个新的server()即可。

一个简单的例子

// Require diet
var server = require('diet');

// Main domain
var app = server()
app.listen('http://example.com/')
app.get('/', function($){
    $.end('hello world ')
})

// Sub domain
var sub = server()
sub.listen('http://subdomain.example.com/')
sub.get('/', function($){
    $.end('hello world at sub domain!')
})

// Other domain
var other = server()
other.listen('http://other.com/')
other.get('/', function($){
    $.end('hello world at other domain')
})

分离您的应用

如果您希望为您的应用设置不同的文件夹,那么您可以拥有如下文件夹结构:

/server
   /yourApp
       /node_modules
       index.js
   /yourOtherApp
       /node_modules
       index.js
   /node_modules
   index.js

/server/index.js中,您需要每个应用程序的文件夹:

require('./yourApp')
require('./yourOtherApp')

/server/yourApp/index.js中,您可以设置第一个域,例如:

// Require diet
var server = require('diet')

// Create app
var app = server()
app.listen('http://example.com/')
app.get('/', function($){
    $.end('hello world ')
})

/server/yourOtherApp/index.js中,您可以设置第二个域,例如:

// Require diet
var server = require('diet')

// Create app
var app = server()
app.listen('http://other.com/')
app.get('/', function($){
    $.end('hello world at other.com ')
});

阅读更多:

答案 2 :(得分:18)

嗯......为什么你认为nodejs应该充当代理。我建议运行几个节点应用程序在不同的端口上侦听。然后使用nginx将请求转发到正确的端口。如果使用单个节点,您也会遇到单点故障。如果该应用程序崩溃,则所有网站都会关闭。

答案 3 :(得分:12)

使用nginx作为反向代理。

http://www.nginxtips.com/how-to-setup-nginx-as-proxy-for-nodejs/

Nginx以缓存,静态文件处理,ssl和负载平衡的形式为您的应用程序带来了许多好处。

答案 4 :(得分:9)

我有一个我在网站上使用的API,下面是我的配置。我也有SSL和GZIP,如果有人需要它,请评论我。

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

var proxy_web = new httpProxy.createProxyServer({
        target: {
            host: 'localhost',
            port: 8080
        }
    });

    var proxy_api = new httpProxy.createProxyServer({
        target: {
            host: 'localhost',
            port: 8081
        }
    });

    http.createServer(function(req, res) {
        if (req.headers.host === 'http://www.domain.com') {
            proxy_web.proxyRequest(req, res);
            proxy_web.on('error', function(err, req, res) {
                if (err) console.log(err);
                res.writeHead(500);
                res.end('Oops, something went very wrong...');
            });
        } else if (req.headers.host === 'http://api.domain.com') {
            proxy_api.proxyRequest(req, res);
            proxy_api.on('error', function(err, req, res) {
                if (err) console.log(err);
                res.writeHead(500);
                res.end('Oops, something went very wrong...');
            });
        }
    }).listen(80);

答案 5 :(得分:6)

如果您使用的是connect / express服务器,则可以看到vhost中间件。它将允许多个域(子域)用于服务器地址。

您可以按照here给出的示例,它看起来与您需要的完全相同。

答案 6 :(得分:4)

最好的方法是使用Express的vhost中间件。查看本教程以获得分步说明:

http://shamadeh.com/blog/web/nodejs/express/2014/07/20/ExpressMultipleSites.html

答案 7 :(得分:3)

这是我最简单的没有任何中间件或代理的演示项目 这只需要几个代码就足够了。

https://github.com/hitokun-s/node-express-multiapp-demo

通过这种结构,您可以轻松地单独设置和维护每个应用程序 我希望这对你有所帮助。

答案 8 :(得分:3)

首先安装foreverbouncy

然后编写启动脚本。在此脚本中,将规则添加到iptables防火墙实用程序,以告知它将端口80上的流量转发到端口8000(或您选择的任何其他内容)。在我的例子中,8000是我运行弹性的地方

sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8000

永远使用,让我们告诉脚本在端口8000上运行弹性

forever start --spinSleepTime 10000 /path/to/bouncy /path/to/bouncy/routes.json 8000

routes.json就像

{
    “subdomain1.domain.com" : 5000,
    “subdomain2.domain.com" : 5001,
    “subdomain3.domain.com" : 5002
}

NodeJS application1,application2和application3分别在端口5000,5001和5002上运行。

我可以找到我在我的案例中使用的脚本here,您可能需要更改一点以适应您的环境。

我还在更多细节上写了这个,你可以找到它here

答案 9 :(得分:1)

使用香草Node.js的方法如下:

const http = require('http')
const url = require('url')
const port = 5555
const sites = {
  exampleSite1: 544,
  exampleSite2: 543
}

const proxy = http.createServer( (req, res) => {
  const { pathname:path } = url.parse(req.url)
  const { method, headers } = req
  const hostname = headers.host.split(':')[0].replace('www.', '')
  if (!sites.hasOwnProperty(hostname)) throw new Error(`invalid hostname ${hostname}`)

  const proxiedRequest = http.request({
    hostname,
    path,
    port: sites[hostname],
    method,
    headers 
  })

  proxiedRequest.on('response', remoteRes => {
    res.writeHead(remoteRes.statusCode, remoteRes.headers)  
    remoteRes.pipe(res)
  })
  proxiedRequest.on('error', () => {
    res.writeHead(500)
    res.end()
  })

  req.pipe(proxiedRequest)
})

proxy.listen(port, () => {
  console.log(`reverse proxy listening on port ${port}`)
})

很简单吧?

答案 10 :(得分:1)

基于@Michaaatje和@papiro,一种非常简单的方法:

假设您有一些典型的页面,例如...

var app = express()
app.use(sess)
app.use(passport.initialize())
app.use(passport.session())
app.use('/static', express.static('static'))

app.get('/', ensureLoggedIn("/loginpage"), function(req, res, next) {
    ...
})

app.get('/sales', ensureLoggedIn("/loginpage"), function(req, res, next) {
    ...
})

app.get('/about', ensureLoggedIn("/loginpage"), function(req, res, next) {
    ...
})

app.post('/order', ensureLoggedIn("/loginpage"), urlencodedParser, (req, res) => {
    ...
})

..依此类推。

说主域名是“ abc.test.com”

但是您有一个“备用”域(可能是客户),即“ customers.test.com”。

只需添加此...

var app = express()
app.use(sess)
app.use(passport.initialize())
app.use(passport.session())
app.use('/static', express.static('static'))

app.use((req, res, next) => {
    req.isCustomer = false
    if (req.headers.host == "customers.test.com") {
        req.isCustomer = true
    }
    next();
})

然后就很简单...

app.get('/', ensureLoggedIn("/loginpage"), function(req, res, next) {
    if (req.isCustomer) {
        .. special page or whatever ..
        return
    }
    ...
})

app.get('/sales', ensureLoggedIn("/loginpage"), function(req, res, next) {
    if (req.isCustomer) {
        res.redirect('/') .. for example
        return
    }
    ...
})

app.get('/about', ensureLoggedIn("/loginpage"), function(req, res, next) {
    if (req.isCustomer) { ... }
    ...
})

app.post('/order', ensureLoggedIn("/loginpage"), urlencodedParser, (req, res) => {
    if (req.isCustomer) { ... }
    ...
})

感谢@Michaaatje和@papiro。

答案 11 :(得分:0)

来自数字海洋的guide是一种很好的方式。它使用pm2模块来守护你的应用程序(将它们作为服务运行)。不需要像Forever这样的其他模块,因为它会在崩溃时自动重启你的应用程序。它具有许多功能,可帮助您监视服务器上运行的各种应用程序。这太棒了!

答案 12 :(得分:0)

获取请求和响应对象时,可以通过“ request.headers.host” ...(不是ip,实际上是域)来获取域。