我有一个绑定了单个 IP 的 linux 服务器。我想在这个 IP 上的这个服务器上托管多个 Node.js 站点,每个(显然)都有一个唯一的域或子域。我希望它们都在端口 80 上。
我有什么选择来做到这一点?
一个明显的解决方案似乎是让 node.js Web 应用程序为所有域提供服务,该应用程序充当代理并传递到在唯一端口上运行的其他 node.js 应用程序。
我有一个绑定了单个 IP 的 linux 服务器。我想在这个 IP 上的这个服务器上托管多个 Node.js 站点,每个(显然)都有一个唯一的域或子域。我希望它们都在端口 80 上。
我有什么选择来做到这一点?
一个明显的解决方案似乎是让 node.js Web 应用程序为所有域提供服务,该应用程序充当代理并传递到在唯一端口上运行的其他 node.js 应用程序。
选择以下之一:
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 ')
});
嗯...为什么您认为 nodejs 应该充当代理。我会建议运行几个节点应用程序监听不同的端口。然后使用 nginx 将请求转发到正确的端口。如果使用单个 nodejs,您还将遇到单点故障。如果该应用程序崩溃,那么所有网站都会关闭。
我有一个在网站上使用的 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);
使用 nginx 作为反向代理。
http://www.nginxtips.com/how-to-setup-nginx-as-proxy-for-nodejs/
Nginx 以缓存、静态文件处理、ssl 和负载平衡的形式为您的应用程序带来了许多好处。
如果您使用的是连接/快速服务器,您可以看到vhost
中间件。它将允许多个域(子域)用于服务器地址。
您可以按照此处给出的示例进行操作,它看起来完全符合您的需要。
以下是使用 vanilla 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}`)
})
很简单吧?
然后编写启动脚本。在此脚本中,向 iptables 防火墙实用程序添加一条规则,告诉它将端口 80 上的流量转发到端口 8000(或您选择的任何其他端口)。在我的示例中,8000 是我运行有弹性的地方
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8000
永远使用,让我们告诉脚本在端口 8000 上运行 bouncy
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 端口。
我在我的案例中使用的脚本可以在这里找到,您可能需要进行一些更改以适应您的环境。
我也写了更详细的内容,你可以在这里找到。
这是我最简单的演示项目,没有任何中间件或代理。
这只需要几个代码,就足够了。
https://github.com/hitokun-s/node-express-multiapp-demo
使用这种结构,您可以轻松地独立设置和维护每个应用程序。
我希望这对你有帮助。
从字面上看,当你获取请求和响应对象时,你可以通过“request.headers.host”获取域...(不是IP地址,实际上是域)。
基于@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。
这可以通过redbird超级轻松地完成。假设您有两个域名example.com
和example1.com
两个网站在端口8000
和8001
.
您可以通过以下脚本为这两个网站设置反向代理。
var proxy = require('redbird')({port: 80});
proxy.register("example.com", "http://localhost:8000");
proxy.register("example1.com", "http://localhost:8001");
您可以使用进程管理工具,例如pm2
运行脚本,以便在您关闭 shell 后继续提供服务。
这个来自数字海洋的指南是一个很好的方式。它使用 pm2 模块来守护您的应用程序(将它们作为服务运行)。不需要像 Forever 这样的额外模块,因为它会在你的应用程序崩溃时自动重启。它具有许多功能,可帮助您监控服务器上运行的各种应用程序。真是太棒了!