我有一个用 Node 编写的非常简单的日志记录应用程序,它在 mongo 中存储数据。它可以正常运行一段时间(一个小时),然后连接数量激增,我的所有写入都会在连接断开之前暂时失败(大概是超时)。我知道调用 db.close() 很重要,而且 Node 基于事件的异步方面使得在何处进行该调用并不简单。
在我的请求处理程序中,我有:
//val is an object previously defined
database.writeRecord(val)
database.userExists(val['cookie'], function(c){//returns 1 if user exists, 0 if not
if(c==0)
database.createNewUserProfile(val['cookie'],'campaign',val, {cid:cid, event:event});
else
database.attachEventToUserProfile(val['cookie'], 'campaign',val, {cid:cid, event:event});
});
然后,在我的数据库处理程序中,我有以下函数(请原谅复制/粘贴的长度):
function writeRecord(object_passbyreference){
//make a deep copy
var value = new Object();
for (var attr in object_passbyreference) {
value[attr] = object_passbyreference[attr];
}
if(additionalattributes!=undefined){//is there anything else i want to throw in this record?
for (var attr in additionalattributes)
value[attr] = additionalattributes[attr];
}
dbname='beacon';
collectionname='testcollection';
var db = new Db(dbname, new Server(host, port, {}), {native_parser:false});
db.open(function(err, db) {
if(db === null)
console.log(' db is undefined');
else{
db.collection(collectionname, function(err, collection) {
collection.insert(value, function(err,doc){
if(err) {
console.log('Insert ERROR!!!!! Is the database running? '+JSON.stringify(err));
}
db.close();
}) // collection.insert
}); //db.collection
}
}); // db.open
}
function userExists(cookieid, callback){
var db = new Db('beacon', new Server(host, port, {}), {native_parser:false});
db.open(function(err, db) {//opendb++
if(db === null)
console.log(' db is undefined - profile');
else{
db.collection('userprofiles', function(err, collection) {
collection.find({cookie:cookieid}).toArray(function(e, results) {
if(e){
console.log (' ERROR IN saveUserProfileEvent error:'+JSON.stringify(e)+" cookie:"+JSON.stringify({cookie:cookieid}));
}
else{//the query went alright, callback the count ...
callback(results.length)//returns the size of the result set
}
db.close();
})
})
}
})
}
function createNewUserProfile(cookieid, eventtype, object_passbyreference, additionalattributes){
//make a deep copy, clone it
var object = new Object();
for (var attr in object_passbyreference) {
if(attr!='cookie')
object[attr] = object_passbyreference[attr];
}
if(additionalattributes!=undefined){//is there anything else i want to throw in this record?
for (var attr in additionalattributes)
object[attr] = additionalattributes[attr];
}
var recordtosave=new Object();
recordtosave['cookie']=cookieid;
recordtosave['items']=1;//keep this here, maybe just for fun, let's see if we can keep a count of total entries for this given user
recordtosave['campaign']=new Array();//new Array();
recordtosave['survey']=new Array();
recordtosave[eventtype]=[object];
recordtosave['demographics']=new Object();
recordtosave['demographics']['age']=functionobj.getAge();
recordtosave['demographics']['gender']=functionobj.getGender();
recordtosave['demographics']['income']=functionobj.getIncome();
var db = new Db('beacon', new Server(host, port, {}), {native_parser:false});
db.open(function(err, db) {//opendb++
if(db === null)
console.log(' db is undefined - profile');
else{
db.collection('userprofiles', function(err, collection) {
collection.insert(recordtosave, function(err,doc){
if(err){
console.log(' ERROR Adding new user '+cookieid);
}
else{
console.log('Added new user '+cookieid);
}
db.close();
})
})
}
})
}
function attachEventToUserProfile(cookieid, eventtype, object_passbyreference, additionalattributes){
var object = new Object();
for (var attr in object_passbyreference) {
if(attr!='cookie')
object[attr] = object_passbyreference[attr];
}
if(additionalattributes!=undefined){//is there anything else i want to throw in this record?
for (var attr in additionalattributes)
object[attr] = additionalattributes[attr];
}
var db = new Db('beacon', new Server(host, port, {}), {native_parser:false});
db.open(function(err, db) {
if(db === null)
console.log(' db is undefined - profile');
else{
db.collection('userprofiles', function(err, collection) {
eventtopush=new Object();
eventtopush[eventtype]=object
collection.update({cookie: cookieid}, {$inc: { 'items' : 1 }, $push: eventtopush}, function(e,doc){
if(e){
console.log(' ERROR Updating user '+cookieid);
}
else{
console.log('Updated user '+cookieid);
}
db.close();
});
})
}
});
}
我所有的函数都是这样的形式:
function f(param, callback){
db=new db;
db.open(...
db.collection(....
db.find/insert(....
callback()
db.close()
}
这样对吗?我想要 db.close 在最内层函数调用的末尾,对吗?这意味着它会在一切都完成后执行?这是在 Node 中执行 mongo 查询的正确方法吗?
查看 mongostat,我看到我的连接非常低且平坦,然后在一段时间内,它们飙升至 ~800,我的写入开始失败(注意,时间间隔为 15 秒):
72 55 38 0 0 332 1.02g 62m 0 90k 307k 13 RTR 21:01:26
68 52 37 0 0 316 1.03g 62m 0 85k 250k 12 RTR 21:01:41
81 65 50 0 0 368 1.02g 62m 0 101k 280k 5 RTR 21:01:56
70 54 39 0 0 322 1.02g 62m 0 87k 306k 4 RTR 21:02:11
insert query update delete getmore command vsize res faults netIn netOut conn repl time
73 52 36 0 0 334 1.09g 63m 0 88k 235k 79 RTR 21:02:26
73 55 39 0 0 346 1.15g 64m 0 91k 250k 148 RTR 21:02:41
70 59 42 0 0 328 1.02g 62m 0 90k 269k 26 RTR 21:02:56
73 58 43 0 0 346 1.02g 62m 0 93k 303k 3 RTR 21:03:11
71 55 41 0 0 337 1.02g 62m 0 90k 243k 16 RTR 21:03:26
69 55 40 0 0 329 1.02g 62m 0 88k 322k 8 RTR 21:03:41
70 56 42 0 0 338 1.02g 62m 0 91k 261k 5 RTR 21:03:56
67 52 38 0 0 316 1.02g 62m 0 85k 261k 3 RTR 21:04:11
64 50 36 0 0 306 1.02g 62m 0 82k 243k 25 RTR 21:04:26
61 48 37 0 0 294 1.04g 62m 0 78k 259k 32 RTR 21:04:41
insert query update delete getmore command vsize res faults netIn netOut conn repl time
68 53 37 0 0 314 1.02g 62m 0 85k 241k 7 RTR 21:04:56
65 53 41 0 0 319 1.02g 62m 0 85k 229k 3 RTR 21:05:11
71 55 40 0 0 337 1.02g 62m 0 91k 274k 14 RTR 21:05:26
63 47 35 0 0 297 1.07g 63m 0 79k 220k 63 RTR 21:05:41
64 52 37 0 0 298 1.02g 62m 0 81k 230k 7 RTR 21:05:56
67 53 39 0 0 322 1.02g 62m 0 87k 230k 4 RTR 21:06:11
68 53 38 0 0 321 1.02g 62m 0 86k 273k 3 RTR 21:06:26
70 56 41 0 0 336 1.02g 62m 0 90k 275k 3 RTR 21:06:41
64 51 38 0 0 310 1.02g 62m 0 82k 220k 4 RTR 21:06:56
66 51 38 0 0 315 1.02g 62m 0 84k 290k 21 RTR 21:07:11
insert query update delete getmore command vsize res faults netIn netOut conn repl time
62 50 38 0 0 299 1.02g 62m 0 80k 240k 5 RTR 21:07:26
65 49 36 0 0 308 1.02g 62m 0 82k 235k 36 RTR 21:07:41
68 51 36 0 0 298 1.02g 62m 0 81k 255k 6 RTR 21:07:56
69 53 37 0 0 319 1.02g 62m 0 85k 235k 5 RTR 21:08:11
66 52 37 0 0 312 1.02g 62m 0 84k 236k 6 RTR 21:08:26
65 51 36 0 0 305 1.02g 62m 0 82k 214k 5 RTR 21:08:41
68 53 38 0 0 320 1.02g 62m 0 85k 265k 9 RTR 21:08:56
70 53 36 0 0 319 1.02g 62m 0 85k 226k 19 RTR 21:09:11
69 52 37 0 0 312 1.02g 62m 0 84k 270k 4 RTR 21:09:26
67 51 36 0 0 311 1.04g 63m 0 83k 256k 19 RTR 21:09:41
insert query update delete getmore command vsize res faults netIn netOut conn repl time
70 54 40 0 0 325 1.02g 62m 0 88k 288k 4 RTR 21:09:56
69 52 36 0 0 317 1.03g 62m 0 85k 272k 14 RTR 21:10:11
67 53 39 0 0 321 1.03g 62m 0 86k 253k 13 RTR 21:10:26
70 55 39 0 0 330 1.03g 62m 0 88k 264k 12 RTR 21:10:41
70 54 39 0 0 332 1.03g 63m 0 89k 264k 30 RTR 21:10:56
69 52 36 0 0 319 1.07g 63m 0 85k 288k 73 RTR 21:11:11
61 43 32 0 0 291 1.19g 66m 0 75k 250k 208 RTR 21:11:26
62 42 30 0 0 285 1.32g 68m 0 74k 252k 321 RTR 21:11:41
66 52 38 0 0 315 1.33g 69m 0 84k 274k 341 RTR 21:11:56
68 42 30 0 0 302 1.51g 72m 0 78k 217k 500 RTR 21:12:11
insert query update delete getmore command vsize res faults netIn netOut conn repl time
53 27 20 0 0 256 1.78g 77m 0 62k 175k 780 RTR 21:12:26
22 19 15 0 0 244 1.77g 78m 0 58k 158k 771 RTR 21:12:41
21 17 11 0 0 245 1.75g 77m 0 59k 139k 755 RTR 21:12:56
7 4 3 0 0 218 1.77g 78m 0 49k 103k 772 RTR 21:13:11
2 1 0 0 0 214 1.77g 77m 0 47k 85k 773 RTR 21:13:26
0 0 0 0 0 208 1.77g 77m 0 45k 79k 773 RTR 21:13:41
61 60 41 0 0 323 1.49g 73m 0 91k 338k 489 RTR 21:13:56
79 73 50 0 0 358 1.16g 65m 0 104k 328k 153 RTR 21:14:11
74 50 32 0 0 315 1.22g 66m 0 84k 241k 220 RTR 21:14:26
72 51 35 0 0 303 1.19g 66m 0 83k 290k 189 RTR 21:14:41
insert query update delete getmore command vsize res faults netIn netOut conn repl time
74 52 35 0 0 310 1.19g 66m 0 84k 224k 180 RTR 21:14:56
80 58 39 0 0 337 1.14g 65m 0 92k 344k 127 RTR 21:15:11
81 48 30 0 0 314 1.22g 67m 0 83k 242k 215 RTR 21:15:26
84 58 37 0 0 332 1.15g 65m 0 91k 275k 152 RTR 21:15:41
82 58 39 0 0 328 1.1g 64m 0 90k 331k 83 RTR 21:15:56
78 53 36 0 0 317 1.08g 64m 0 86k 271k 89 RTR 21:16:11
82 47 32 0 0 314 1.19g 66m 0 83k 257k 200 RTR 21:16:26
80 52 37 0 0 318 1.24g 67m 0 85k 304k 234 RTR 21:16:41
21 点 11 分 26 秒左右,连接数迅速上升,流量没有明显增加。你可以看到之前有很长一段时间连接很低且稳定。
有人能给我指出正确的方向吗?
在下面的帮助下,我得到了解决方案。基本上,您将 app.listen(port) 放在 db.open() 中。然后,除此之外,仍然在 main.js 中,您将对 db 的引用传递给您的路径处理程序。然后将其一直传递到实际的数据库调用,您是否获得了集合并进行了查询。然后根本不要调用 db.close()。
主要.js:
mongodb = require('mongodb');
var serverOptions = {
'auto_reconnect': true,
'poolSize': 50
};
var serv = new mongodb.Server('localhost', 27017, serverOptions);
var db = new mongodb.Db('beacon', serv);
app.get('/log', function(req,res){ log.request(req,res, db) });//writes events
db.open(function (error, db) {
if (!module.parent) {
app.listen(8888);
console.log("Express server listening on port %d", app.address().port)
}
});
日志.js:
function request(req,res, db){
//build val object
database.writeRecord(db, val)
}
数据库.js:
function writeRecord(db, value){
collectionname='testwritespeed';
db.collection(collectionname, function(err, collection) {
collection.insert(value, function(err,doc){
if(err) {
console.log('Insert ERROR!!!!! Is the database running? '+JSON.stringify(err));
}
console.log(doc)
//don't do db.close() !!!!!
}) // collection.insert
}); //db.collection
}
最佳答案
当您创建一个新的 Db 对象然后对其调用 open 时,您实际上正在创建一个包含五个连接的连接池(默认情况下)。然后,当您调用 db.close如果没有任何参数,池中的连接实际上并没有关闭,而是保留下来以防很快再次需要它们。
因为您在每次调用您的模块时都这样做,所以很容易看出您是如何耗尽连接的。
相反,您应该在应用程序启动时创建单个 Db 连接池,该连接池被传递到您的模块(或模块自行创建),您的模块的所有方法都可以使用。
Db 连接池支持多个未完成的操作,最大可达连接池的大小。
主要.js:
mongodb = require('mongodb');
var serverOptions = {
'auto_reconnect': true,
'poolSize': 50
};
var serv = new mongodb.Server('localhost', 27017, serverOptions);
var db = new mongodb.Db('beacon', serv);
app.get('/log', function(req,res){
log.request(req,res, db);
});
db.open(function (error, db) { // Both the db var and the db parameter are the same object
if (!module.parent) {
app.listen(8888);
console.log("Express server listening on port %d", app.address().port)
}
});
数据库.js:
function writeRecord(db, value){
collectionname='testwritespeed';
db.collection(collectionname, function(err, collection) {
collection.insert(value, function(err, doc){
if (err) {
console.log('Insert ERROR!!!!! Is the database running? '+JSON.stringify(err));
}
console.log(doc);
// Do NOT close db here!
});
});
}
关于node.js mongodb 连接峰值,写入失败,连接池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13185914/
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类
我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r
我正在尝试在Rails上安装ruby,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf
我想知道Ruby用来在命令行打印这些东西的输出流:irb(main):001:0>a="test"=>"test"irb(main):002:0>putsatest=>nilirb(main):003:0>a=>"test"$stdout是否用于irb(main):002:0>和irb(main):003:0>?而且,在这两次调用之间,$stdout的值是否有任何变化?另外,有人能告诉我打印/写入这些内容的Ruby源代码吗? 最佳答案 是的。而且很容易向自己测试/证明。在命令行试试这个:ruby-e'puts"foo"'>test.
我需要一个非常简单的字符串验证器来显示第一个符号与所需格式不对应的位置。我想使用正则表达式,但在这种情况下,我必须找到与表达式相对应的字符串停止的位置,但我找不到可以做到这一点的方法。(这一定是一种相当简单的方法……也许没有?)例如,如果我有正则表达式:/^Q+E+R+$/带字符串:"QQQQEEE2ER"期望的结果应该是7 最佳答案 一个想法:你可以做的是标记你的模式并用可选的嵌套捕获组编写它:^(Q+(E+(R+($)?)?)?)?然后你只需要计算你获得的捕获组的数量就可以知道正则表达式引擎在模式中停止的位置,你可以确定匹配结束
我正在尝试在配备ARMv7处理器的SynologyDS215j上安装ruby2.2.4或2.3.0。我用了optware-ng安装gcc、make、openssl、openssl-dev和zlib。我根据README中的说明安装了rbenv(版本1.0.0-19-g29b4da7)和ruby-build插件。.这些是随optware-ng安装的软件包及其版本binutils-2.25.1-1gcc-5.3.0-6gconv-modules-2.21-3glibc-opt-2.21-4libc-dev-2.21-1libgmp-6.0.0a-1libmpc-1.0.2-1libm
require"socket"server="irc.rizon.net"port="6667"nick="RubyIRCBot"channel="#0x40"s=TCPSocket.open(server,port)s.print("USERTesting",0)s.print("NICK#{nick}",0)s.print("JOIN#{channel}",0)这个IRC机器人没有连接到IRC服务器,我做错了什么? 最佳答案 失败并显示此消息::irc.shakeababy.net461*USER:Notenoughparame
一段时间以来,我一直在使用open_uri下拉ftp路径作为数据源,但突然发现我几乎连续不断地收到“530抱歉,允许的最大客户端数(95)已经连接。”我不确定我的代码是否有问题,或者是否是其他人在访问服务器,不幸的是,我无法真正确定谁有问题。本质上,我正在读取FTPURI:defself.read_uri(uri)beginuri=open(uri).readuri=="Error"?nil:urirescueOpenURI::HTTPErrornilendend我猜我需要在这里添加一些额外的错误处理代码...我想确保我采取一切预防措施来关闭所有连接,这样我的连接就不是问题所在,但是我