ExpressJS - 如何处理同步请求?请求似乎彼此阻止。

时间:2014-01-21 10:03:47

标签: node.js asynchronous express

我有以下代码

var express = require('express');
var routes = require('./routes');    
var http = require('http');
...
app.get('/a',function(){
  Card.findCards(function(err, result){  //Mongoose schema
    res.send(result); //Executes a query with 9000 records
  })  
});
app.get('/b', function(req, res){
  res.send("Hello World");
});

我发现当我使用localhost / a时,需要大约2.3秒才能完成。这并不奇怪,因为它从数据库中获取了相当多的数据。但是我发现如果在加载/ a时我得到GET / b,b将不会显示。好像对/ a的调用阻止了对/ b的调用。

这是表达应该如何工作吗?我一直在假设各个路由是异步的,因为它们接受回调但看起来像express一次只能处理一个请求。在调用res.end()之前,不会处理任何其他请求。我错过了我需要做的任何配置吗?

作为参考,这是我连接到mongoose的方式

mongoose.connect(dbConnectionString, {server:{poolSize:25}});

这是我的http服务器初始化部分

http.globalAent.maxSockets = 20; // or whatever

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

编辑:以下是卡片模型和相关架构+功能的代码

//Card.js
var mongoose = require('mongoose')
  , Schema = mongoose.Schema;

var CardSchema = new Schema({
  _id : {type: String},
  stores : [{
        store: {type: Schema.Types.ObjectId, ref:'StoreModel', required: true}
      , points: {type: Number, required: true}
  }]
});

exports.findCards = function(callback){
  var query = Card.find({}, callback); 
}

3 个答案:

答案 0 :(得分:2)

我遇到了同样的问题,设置类似于你的设置。有两个问题,它们都具有相同的根本原因:节点具有非阻塞I / O操作,但(如bbozo所指出的)CPU密集型操作会阻止它。

第一个问题在于你的猫鼬电话。在mongoose从您的集合中检索文档后,它会将它们转换为mongoose对象。如果您获得9000条记录,则会执行9000次。有问题的行是在mongoose的query.js库中;检查其completeMany函数的for循环,找到相关的阻塞操作。

当Express将生成的JSON对象字符串化以发送您的响应时,会出现第二个问题。罪魁祸首是Express res.json库下的response.js功能。对于较大的响应,stringify的阻塞性质将会很明显。

我不太清楚如何解决这个问题。您可以尝试使用mongodb的本机库,而不是猫鼬。您也可以尝试修补Express,以便它使用JSON流调用而不是阻塞stringify。查询和响应的分页也会有所帮助,但我知道它的实现并不是很简单。

答案 1 :(得分:0)

我会尝试:)

Afaik Node.js在一般意义上不是异步的,它只是非阻塞,如果一个连接什么都不做,那么做某事的另一个连接不会被连接无效阻塞,

需要大量反应器CPU时间的事情(比如加载大量数据)会阻塞事件循环,尝试以较小的块获取数据

答案 2 :(得分:0)

您可以设置精益选项。

启用精益选项的查询返回的文档是纯JavaScript对象,而不是MongooseDocuments。他们没有使用保存方法,getter / setter或其他Mongoose魔法。

示例:

new Query().lean() // true
new Query().lean(true)
new Query().lean(false)

Model.find().lean().exec(function (err, docs) {
  docs[0] instanceof mongoose.Document // false
});

请参阅mongoose documentation