NodeJS在多次请求后无限期地挂起

我有一个nodeJS(v.0.10.23)代理连接到postgres数据库(node-postgres模块v2.1.0),以及返回各种json数据的pgpool-II。

回到当天,这是如何处理连接错误:

var after = function(callback) { return function(err, queryResult) { if(err) { response.writeHead(500, _header); console.log("ERROR: 500"); console.log(err); return response.end(JSON.stringify({error: err})); } callback(queryResult) } }; 

基本上它所做的是在没有错误的情况下消耗响应。

可以在这里find一个深入的解释: Node js – http.request()连接池的问题

使用上面的函数,我有这样的东西:

 pg.connect(_conString, after(function(err, client, done) { client.query(sql, after(function(result) { ... done(); } 

由于当函数传递到after()scallback函数时上下文丢失了,所以我放弃了使用pg.connect()传递的先天done()方法的能力。

删除后解决了这个问题,但随后,在适当的时间,并有相当数量的客户端拉数据,节点将挂起,直到它被重置。

是否有消耗各种asynchronous响应的不同方式?

或者可能是一种将pg.connect上下文传递给callback的方法?

那么,当然,你失去了done() ,你永远不会在你的after()函数中传递第三个参数给你的callback函数。

 function after(cb) { return function() { // you're using this function in a context where the arguments // passed in could be anything. the only constant is that the first // argument is the error, if any if (arguments[0]) { response.writeHead(500, _header); console.log("ERROR: 500"); console.log(err); return response.end(JSON.stringify({error: arguments[0]})); } // apply the entire argument list to the callback, without modification cb.apply(cb, arguments); }; } 

…这也解决了通过queryResultvariables传递client的可疑约定。

看到最后一个例子(使用工厂函数和传递响应),使用工厂函数是非常有趣的,因为它节省了代码

 app.get('/parallel',function(request,response,next){ function err(err) { console.log(err.stack); response.end('error'+err.stack); } function send(data) { response.end(JSON.stringify(data)) } pg.connect(config, function(err, client, done) { if(err){done();return err(err);} client.query("SELECT * FROM NOW()", function(err, result) { done(); if(err){return err (err);} send(result); }, 0) }) }) 

你可以尝试使用可乐的asynchronous到select。

npm安装asynchronous

 // an example using an object instead of an array var x1=null; async.series({// in javascript the creation order is preserved in Object.keys one: function(callback){ setTimeout(function(){ x1=3; callback(null, 1); }, 200); }, two: function(callback){ console.log('select where x1='+x1); setTimeout(function(){ callback(null, 2); }, 100); } }, function(err, results) {// called instantly if there is an error // results is now equal to: {one: 1, two: 2} }); 

单选工厂的callback

 function makesenderr(response){ return function senderr(err,ok) { console.log(err.stack); response.end('error'+err.stack); } } function makesendjson(response){ return function sendjson(data) { response.end(JSON.stringify(data)) } } function tryconn(err,ok){ return function(errarg, client, done) { if(errarg){done();return err(errarg);} ok(client,done); } } function doneerrok(done,err,ok){ return function(errarg, result) { done(); if(errarg){return err(errarg);} ok(result); } } var async=require('async') app.get('/foo',function(request,response,next){ var senderr=makesenderr(response) var sendjson=makesendjson(response) pg.connect(config, tryconn(senderr,function(client,done){ client.query("SELECT one FROM t1",doneerrok(done,senderror,sendjson), 0) })) }) 

使用工厂function和传递响应

  function senderr(response,err) {//add headers here console.log(err.stack); response.end('error'+err.stack); } function sendjson(response,data) {//add headers here response.end(JSON.stringify(data)) } function tryconn(response,ok){ return function(err, client, done) { if(err){done();return senderr(response,err);} ok(client,done); } } function donerespok(done,response,ok){ return function(err, result) { done(); if(err){return err(response,err);} ok(response,result); } } function respok(response,ok){ return function(err, result) { done(); if(err){return err(response,err);} ok(response,result); } } function donecb(done,cb){ return function(){done();cb.apply(this,arguments);} } var async=require('async') app.get('/foo',function(request,response,next){ pg.connect(config, tryconn(response,function(client,done){ client.query("SELECT one FROM t1",donerespok(done,response,sendjson), 0) })) }) app.get('/series',function(request,response,next){ pg.connect(config, tryconn(response,function(client,done){ var one={}; async.series({ one: function(cb){ client.query("SELECT one FROM t1", function(err, result) { one=result;cb(err,result); }, 0) }, two: function(cb){ client.query("SELECT two FROM t2 where one="+one[0].one,cb, 0) } }, // results is now equal to: {one: [{one:1}], two: [{two:2},{two:2}]} donerespok(done,response,sendjson) ); })) }) app.get('/parallel',function(request,response,next){ async.parallel({ one: function(cb){ pg.connect(config, tryconn(response,function(client,done){ client.query("SELECT one FROM t1",donecb(done,cb), 0) })) }, two: function(cb){ pg.connect(config, tryconn(response,function(client,done){ client.query("SELECT two FROM t2",donecb(done,cb), 0) })) } }, // results is now equal to: {one: [{one:1},{one:2}], two: [{two:1},{two:2}]} respok(response,sendjson) ); }) 

首先,你应该增加你的连接池,如果你还没有,这看起来像你不想限制6个连接。 你也应该设置一个相当低的请求超时。

至于数据的上下文,你有没有考虑绑定pg.connect的this到后函数? 这将允许您在本地上下文中进行访问。

 pg.connect(_conString, after(function(err, client, done) { this.done = done; client.query(sql, (after(function(result) { ... this.done(); }).bind(this)); }); 

粉碎杂志有一个很好的文章,在前几天使用bind() 在这里