mercredi 15 avril 2015

Node server with mongoose getting stuck

I am running into an unexplained behavior with a node program and I was wondering if I could get help from community on troubleshooting this problem. Thanks in advance for your help!


Setup


I have a node web server running behind NGINX, which in turn, is behind Amazon ELB. The ELB is configured to be an SSL/TCP load balancer, not HTTP load balancer. The node server uses MongoDB backend, with mongoose 3.8.25 module.


Code


The following is the equivalent of my code, I tried to extract the relevant piece of code; please refer to the download URL handler.


```javascript // Generated by CoffeeScript 1.7.1 (function() { var MyCsvStream, Q, Schema, TestModel, TestSchema, Transform, downloadData, express, expressApp, fs, getQueryStream, mongoose, start, startServer, util, _;



_ = require("underscore");

mongoose = require("mongoose");

Q = require("q");

express = require("express");

fs = require("fs");

expressApp = express();

Transform = require('stream').Transform;

util = require('util');

MyCsvStream = function() {
return Transform.call(this, {
objectMode: true
});
};

util.inherits(MyCsvStream, Transform);

MyCsvStream.prototype._transform = function(chunk, encoding, callback) {
var csvLine, obj, rowArr;
obj = chunk;
rowArr = [obj.a, obj.b, obj.c, obj.d];
csvLine = rowArr.join(",") + "\n\r";
this.push(csvLine, "utf-8");
return callback();
};

getQueryStream = function(cb) {
var stream;
stream = TestModel.find({}).sort("-d").stream();
return cb(stream);
};


/* Download URL handler */

downloadData = function(req, res) {
var outFileName;
outFileName = "mydownload.csv";
res.header("Content-disposition", "attachment; filename=" + outFileName);
res.type("text/csv");
res.write("a,b,c,d\n\r");
getQueryStream(function(dataStream) {
return dataStream.pipe(new MyCsvStream()).pipe(res);
});
};


/* HTTP SERVER */

startServer = function() {
var server;
expressApp.get("/download", downloadData);
expressApp.get("/ping", function(req, res) {
return res.send("pong\n\r");
});
return server = expressApp.listen(3000, function() {
var host, port;
host = server.address().address;
port = server.address().port;
console.log("Server started at http://%s:%s", host, port);
});
};


/* Main routine. Inserts a bunch of records and starts server */

start = function() {
var db;
db = mongoose.connection;
db.on("open", function() {
var arr, i;
arr = [];
i = 0;
while (i < 100 * 1000) {
arr.push({
a: i,
b: i,
c: i,
d: new Date()
});
i++;
}
console.log("Cleaning up mess from before...");
return TestModel.remove({}, function(err) {
console.log("..Cleaned up prev DB");
if (err) {
console.error(err);
process.exit(1);
}
console.log("Inserting..");
return TestModel.collection.insert(arr, function(err) {
console.log(".. Inserted " + arr.length + " test records");
if (err) {
console.error(err);
process.exit(1);
}
return startServer();
});
});
});
return mongoose.connect("mongodb://localhost/testdb");
};


/* Mongoose Model Def */

Schema = mongoose.Schema;

TestSchema = new Schema({
a: String,
b: String,
c: String,
d: Date
});

TestModel = mongoose.model("TestModel", TestSchema);

start();

}).call(this);


```


Problem


We are trying to stream mongoose query stream to user's stream, via a transform stream. When user hits the download URL, sometimes node seems to be getting stuck for a while. It's as if we have a blocking call somewhere and does not even return static files. It does respond after some time, and may depend on the size of query results. NOTE that I can't recreate my problem with the above snippet code, and also not consistently on the real server.


Question


Is there something wrong with the streaming code? Is it possible to get in to some weird blocking situations streaming this way between MongoDB client and the user http socket? The code is very straightforward, this kind of behavior should never happen since there are no blocking calls anywhere. Any tips on debugging this kind of behavior are greatly appreciated as well.


Aucun commentaire:

Enregistrer un commentaire