Javascript ExpressJS服务器-如何处理多个域
我在玩Express,我想知道“最正确”的方法是处理链接到同一服务器的多个域 假设我们有Javascript ExpressJS服务器-如何处理多个域,javascript,node.js,express,Javascript,Node.js,Express,我在玩Express,我想知道“最正确”的方法是处理链接到同一服务器的多个域 假设我们有 foo.com bar.net baz.com 都指向111.222.333.444。那台机器正在用快车运行NodeJS。我当前的解决方案如下所示: var express = require( 'express' ), app = module.exports = express.createServer(), // ... more lines ... app.get( '/', r
- foo.com
- bar.net
- baz.com
111.222.333.444
。那台机器正在用快车运行NodeJS。我当前的解决方案如下所示:
var express = require( 'express' ),
app = module.exports = express.createServer(),
// ... more lines ...
app.get( '/', routes.index.bind( app ) );
express.createServer()
.use(express.vhost('hostname1.com', require('/path/to/hostname1').app)
.use(express.vhost('hostname2.com', require('/path/to/hostname2').app)
.listen(80)
到目前为止,这是相当简单的。目前唯一的例外是在我的应用程序中。配置调用,我没有调用。使用(express.static())
。这是因为.routes.index()
方法现在看起来是这样的:
var fs = require( 'fs' ),
// ... more lines ...
exports.index = function( req, res ) {
var host = /(\w+\.)?(.*)\.\w+/.exec( req.header( 'host' ) ),
app = this;
switch( host[ 2 ] ) {
case 'foo':
app.use( express.static( '/var/www/foo' ) );
fs.readFile( '/var/www/foo/index.html', 'utf8', fileReadFoo );
break;
case 'bar':
app.use( express.static( '/var/www/bar' ) );
fs.readFile( '/var/www/bar/index.html', 'utf8', fileReadBar );
break;
case 'baz':
// ... lines ...
res.render( 'index', { title: 'Baz Title example' } );
break;
default:
res.send('Sorry, I do not know how to handle that domain.');
}
function fileReadFoo( err, text ) {
res.send( text );
}
function fileReadBar( err, text ) {
res.send( text );
}
};
这里发生的是,我分析host
条目的req.header
,并解析域名。基于此,我调用.static()
方法,以便Express能够提供正确的静态资源等,而且,我只需读取并发送index.html文件的内容。我也尝试使用Jade来提供普通HTML文件,但是Jade中的include
指令只接受相对路径
然而,这确实有效,但我很不确定这是否是一个好的做法
欢迎提供任何建议/帮助
更新
我想我需要更清楚地说明这一点。我决不是初学者。我非常了解ES和其他服务器(如NGINX)的工作原理。我正在寻找关于NodeJS/Express的正确答案。如果使用Node/Express对此没有任何意义,请详细说明。如果使用Node/Express有更好的方法,请解释
谢谢:-)我使用node.js作为前端服务器。它是组织域、静态内容交付、负载控制和许多其他强大功能的最佳解决方案。绝对不需要在节点事件循环中执行此操作。这将决定应用程序的速度。Vadim是。您可以使用以下配置如何响应每个域:
routes.index
可以简化为只处理baz.com
请求:
exports.index = function( req, res ) {
// ... lines ...
res.render( 'index', { title: 'Baz Title example' } );
};
编辑
至于比较:
首先有效地执行开关
,并确定如何基于主机处理所有请求
——类似于:
express.createServer().use(function( req, res, next ) {
switch( req.host ) {
case 'foo.com': express.static( '/var/www/foo' )( req, res, next ); break;
case 'bar.net': express.static( '/var/www/bar' )( req, res, next ); break;
case 'baz.com': app.handle( req, res, next ); break;
default: res.send( ... );
}
}).listen( ... );
它允许您在启动时设置堆栈,以便任何中间件立即可用:
server.stack = [
express.vhost( 'foo.com', ... ),
express.vhost( 'bar.net', ... ),
express.vhost( 'baz.com', ... ),
[Function]
];
// GET http://foo.com/file 404
app.stack = [ app.router ]
// GET http://foo.com/ 200
app.stack = [ app.router, express.static( '/var/www/foo' ) ]
// GET http://foo.com/file 200
app.stack = [ app.router, express.static( '/var/www/foo' ) ]
这些也反映了您可能遇到的问题的两个可能来源:
没有过滤器的相同堆栈
每个应用程序
只有一个中间件堆栈,您使用的所有中间件都将通过应用程序直接添加到该堆栈中。使用(…)
。尽管在条件下添加了一些,但您仍然可以:
app.stack = [
// ...,
app.router,
express.static( '/var/www/foo' ),
express.static( '/var/www/bar' )
];
而且该条件不会改变静态
中间件的响应方式——即通过req.path
,而不是req.host
——仅当它们在堆栈中开始响应时
堆栈状态
而且,如果在发出另一个请求后才添加静态
中间件,那么我认为它们不会立即可用:
server.stack = [
express.vhost( 'foo.com', ... ),
express.vhost( 'bar.net', ... ),
express.vhost( 'baz.com', ... ),
[Function]
];
// GET http://foo.com/file 404
app.stack = [ app.router ]
// GET http://foo.com/ 200
app.stack = [ app.router, express.static( '/var/www/foo' ) ]
// GET http://foo.com/file 200
app.stack = [ app.router, express.static( '/var/www/foo' ) ]
这也可能意味着相同的静态中间件可以多次添加到堆栈中:
// 3x GET http://foo.com/
app.stack = [
app.router,
express.static( '/var/www/foo' ),
express.static( '/var/www/foo' ),
express.static( '/var/www/foo' )
]
让它们的添加取决于其他请求也意味着可能的竞争条件:
// was `foo.com` or `bar.net` first?
app.stack = [
app.router,
express.static( ? ),
express.static( ? )
]
我喜欢用作前端反向代理-这允许您将完全不同的express堆栈作为不同的服务器进程运行(每个进程具有不同的功能,并且为了健壮性而分开)
然后,您可以决定如何路由到不同的端口,这对WebSocket很好
var bouncy = require('bouncy');
bouncy(function (req, bounce) {
if (req.headers.host === 'bouncy.example.com') {
bounce(8000);
}
else if (req.headers.host === 'trampoline.example.com') {
bounce(8001)
}
}).listen(80);
我不得不说,我不认为这样做有什么意义。Node.js具有一个流程设计约束。限制IO对于一个web应用程序来说是一项艰巨的工作,更不用说少数web应用程序了。试图通过使用多个应用程序来抽象这一点会使代码过于复杂,使其无法读取。单个应用程序中的错误可能会影响所有应用程序。这是一个非常不稳定的配置
如果你想看看你是否能做到,我想答案是肯定的。在另一个答案中,类似于vhost的建议。另一方面,我可能会采取某种分离关注点的方式,限制我的应用程序。如果要将其放置在同一服务器盒中,我将执行以下操作:
可用核心数-1是我绑定到单个服务器的域数
每个核心将包含一个绑定到它的node.js进程。它将实现覆盖单个网站的单个web应用程序李>
备用核心将容纳某种类型的“路由器”,可以是nginx解决方案,也可以是路由数据的node.js/express应用程序李>
简言之,不要想着做大,想想做大
缺点:
这是一种不同的缩放方式。你从一个盒子里只能得到这么多的果汁。当我们谈论“多盒子”环境时,我不知道如何扩展这个想法 由于Express使用,我很确定您可以使用Connect的虚拟主机中间件。它的操作与其他产品上的其他vhost模块类似。我没有多个域来测试并向您展示正确的代码,但我认为是这样的:
var express = require( 'express' ),
app = module.exports = express.createServer(),
// ... more lines ...
app.get( '/', routes.index.bind( app ) );
express.createServer()
.use(express.vhost('hostname1.com', require('/path/to/hostname1').app)
.use(express.vhost('hostname2.com', require('/path/to/hostname2').app)
.listen(80)
如果一台Express服务器还不够,那么可以从API中查看Node.Cluster的使用情况。如果这还不够,那么当前的做法是在Express服务器前面放置一个asnyc反向代理,如Nginx,并将代理指向Express服务器。如果不知道约束条件,就很难回答这个问题,这意味着必须在同一进程中运行主机,因此,我将附和其他人所说的,但希望给出更多的上下文
使用node的“最正确”方法是在多个进程中运行主机,并在多个进程中反向代理请求