I have the following piece of code
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");
});
I find that when I make a get on localhost/a, it takes around 2.3 seconds to complete. This isn't really surprising since it fetches quite a bit of data from the database. However I find that if I GET /b while /a is loading, b will not display. It is as if the call to /a is blocking the call to /b.
Is this how express is supposed to work? I've always operated on the assumptions that individual routes are asynchronous since they take in callbacks but it seems like express can only process one request at a time. Until res.end() is called, no other request gets processed. Am I missing any configuration that I need to do?
For reference, this is how I connect to mongoose
mongoose.connect(dbConnectionString, {server:{poolSize:25}});
And this is my http server initialization part
http.globalAent.maxSockets = 20; // or whatever
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
EDIT: Here is the code for the Card Model and associated schema + functions
//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);
}
I've been experiencing the same problem, with a setup similar to yours. There are two issues, both of them with the same root cause: Node has non-blocking I/O operations, but (as bbozo points out) CPU-intensive operations do block it.
The first problem lies in your mongoose call. After mongoose retrieves the documents from your collection, it converts them into mongoose objects. If you get 9000 records, it will do this 9000 times. The lines in question are in mongoose's query.js
library; check out the for loop on its completeMany
function to find the relevant blocking operations.
The second problem comes when Express stringifies the resulting JSON objects to send your response. The culprit is the res.json
function under Express's response.js
library. For a large response the blocking nature of stringify
will be noticeable.
I am not quite sure how to solve this issue. You could probably try to use mongodb's native library, instead of mongoose. You could also try and patch Express so it uses JSON stream calls instead of the blocking stringify. Pagination of your query and response would also help, though I know it's not very simple to implement.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With