`
start_p
  • 浏览: 66441 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

nodejs-mongodb部署在BAE上出现500 no open connections解决办法

阅读更多

    在本地测试好的nodejs应用部署到百度BAE上出现no open connections问题,没有打开的数据库连接,出现这个错误的原因是百度共享mongodb不支持长连接,每隔30秒就会断开,后来就想到断开重连的方式,经过网上查阅,确实有前人是这么做的,自己写的方法不行就用别人的,可是这个问题依旧,反复的折腾就是解决不了,开始怀疑自己的智商。为什么别人的可以连上就我的不行,期间用抛出异常的方式强制应用重启,这样只是治标不治本,还会有一分钟的重启时间不能访问。最后只好一步步测试,每一句代码都输出一下,在BAE上部署后发现连接确实有打开的,可是为什么应用还会报错,看了下错误信息,发现这个错误时有关session的,恍然大悟,我的session用的是mongodb作为存储,它也会断开,但是没有重连机制,所以就一直报错。

    既然找到问题所在,那就解决吧,可是请看以下代码:
app.use(session({
    secret:settings.cookieSecret,
    store:newMongoStore({                     url:"mongodb://"+settings.uid+":"+settings.pwd+"@"+settings.host+":"+settings.port+"/"+settings.db
    })
}));
 
这可没有办法实现重连,于是乎,在网上找到了这篇文章,其中用的是session-mongoose中间件,在查看了github session-mongoose上的文档后发现可以用第三方连接
Using custom connection
 
var mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/mysessionstore");
 
varSessionStore= require("session-mongoose")(express);
var store =newSessionStore({
interval:120000,// expiration check worker run interval in millisec (default: 60000)
connection: mongoose.connection // <== custom connection
});
 正好用的是mongoose,那我就把重连机制的mongoose变量传过来,并安装 session-mongosse,结果又是一个坑,session-mongosse要求的connect版本是2.0的,而我安装的是3.0以上的,我不可能降低版本来适应它吧,这样会导致其他依赖出现问题。还是使用原来的connect-mongo中间件好了,看了一下connect-mongo的文档和源码,有这么一个选项:mongoose_connection in the form: someMongooseDb.connections[0] to use an existing mongoose connection. (optional)
这个用的正好也是mongoose连接,那就好办了
var store =newMongoStore({
//    url:"mongodb://"+settings.uid+":"+settings.pwd+"@"+settings.host+":"+settings.port+"/"+settings.db,
    interval:120000,// expiration check worker run interval in millisec (default: 60000)
    mongoose_connection: connection.mongoose.connection // <== custom connection
});
app.use(session({
    secret:settings.cookieSecret,
    store:store,
    resave:false,
    saveUninitialized:false
}));
  
在MongoStore属性中添加mongoose_connection属性,值为mongoose,这样的话session的连接用的也是查询的,完美解决。
顺带贴上重连机制代码:getConnect.js
/**
* Created by huopanpan on 2014/6/30.
*/
/**
* 连接到mongodb
* 使用mongoose而非mongodb中间件
**/
var mongoose = require('mongoose');
 
var host ="mongo.duapp.com",
port ="8908",
username ="",
password ="",
dbName ="",
url ="mongodb://"+ username +":"+ password +"@"+ host +":"+ port +"/"+ dbName;
 
var recon =true;
function getConnect(){
var opts ={
db:{
native_parser:true
},
server:{
poolSize:5,
auto_reconnect:true
},
user: username,
pass: password
};
// mongoose.connect("mongodb://HahMqSkZWUq9QWHsWceXmG83:XH82hOf5MGzoMUMUkCNj0KdBvecF3mzP@mongo.duapp.com:8908/pQPzvWlctdHpUjrbtFnX");//需要验证账户
// mongoose.connect("mongodb://" + username + ":" + password +"@"+ host + ":" + port + "/" + dbName);//需要验证账户
mongoose.connect(url, opts);
var dbcon = mongoose.connection;
// var dbcon = mongoose.createConnection(url, opts);
dbcon.on('error',function(error){
console.log('connection error');
// throw new Error('disconnected,restart');
dbcon.close();
});
 
//监听关闭事件并重连
dbcon.on('disconnected',function(){
console.log('disconnected');
dbcon.close();
});
dbcon.on('open',function(){
console.log('connection success open');
recon =true;
});
dbcon.on('close',function(err){
console.log('closed');
// dbcon.open(host, dbName, port, opts, function() {
// console.log('closed-opening');
// });
reConnect('*');
});
function reConnect(msg){
console.log('reConnect'+msg);
if(recon){
console.log('reConnect-**');
dbcon.open(host, dbName, port, opts,function(){
console.log('closed-opening');
});
recon =false;
console.log('reConnect-***');
};
console.log('reConnect-end');
}
}
 
exports.getConnect = getConnect;//包含到module.exports对象中,
// 如果module.exports中包含属性或方法则export.XX将被忽略
// Module.exports才是真正的接口,exports只不过是它的一个辅助工具。
// 最终返回给调用的是Module.exports而不是exports。
// 所有的exports收集到的属性和方法,都赋值给了Module.exports。
// 当然,这有个前提,就是Module.exports本身不具备任何属性和方法。
// 如果,Module.exports已经具备一些属性和方法,那么exports收集来的信息将被忽略。
//module.exports = getConnection;//直接导出这个对象
exports.mongoose = mongoose;
 
将mongoose导出供session公用
补充:以上内容理论上解决了问题,但实际还有其他问题需要解决,请查看后续的两篇:
 
 
0
0
分享到:
评论
2 楼 start_p 2014-10-12  
yaCHAO822 写道
getConnect 怎么用啊?

可以在app.js或者其他路由中引入:var getConnect=require('getConnect')();引入getConnect以后直接自执行就会将function getConnect函数执行就可以了
1 楼 yaCHAO822 2014-10-11  
getConnect 怎么用啊?

相关推荐

Global site tag (gtag.js) - Google Analytics