我正在开发一个托管在 EC2 上的像素跟踪应用程序,该应用程序在视频广告的每个请求上都会被调用,因此它会跟踪它何时开始、完成以及是否进行了点击操作。我将 node.js 与 express 一起使用,因为我想尽可能快地响应和 mongoDB/Mongoose,因为它就像一个服务器日志结构。我几乎每毫秒都会收到请求。但是当将文档存储到集合中时,它几乎 100% 占用了大量的 CPU,最后 node.js 启动错误:
GET /pixel/impression/ad1 200 1ms
FATAL ERROR: CALL_AND_RETRY_2 Allocation failed - process out of memory
我认为是猫鼬操作在我移除部件时占用了大部分 cpu,它永远不会挂起。
在 app.js 我有:
var hostSchema = new mongoose.Schema({
ip: String,
date: { type: Date, default: Date.now }
});
var orderSchema = new mongoose.Schema({
name: String,
metricCount: {
impression: { type: Number, default: 0 },
clicks: { type: Number, default: 0 },
complete: { type: Number, default: 0 }
},
impressionHosts: [hostSchema],
clicksHosts: [hostSchema],
completeHosts: [hostSchema]
});
var Order = mongoose.model('order', orderSchema);
var Host = mongoose.model('host', hostSchema);
和快速获取方法:
app.get('/pixel/:metric/:campaignName', function(req, res){
var campaignName = req.params.campaignName;
var metrica = req.params.metric;
Order.find({name: campaignName}, function(err, doc){
newMet = {};
newMet[metrica] = 1;
var incomingHost = new Host({ip: req.ip});
if(doc.length<1){
insertNewElement(campaignName, newMet, metrica, incomingHost);
}else {
updateElement(doc[0], metrica, incomingHost);
}
});
res.end(pixel, 'binary');
});
当我评论“updateElement”函数时,node.js 执行“完美”。这里有这些功能:
function updateElement(doc, metrica, incomingHost){
doc.metricCount[metrica]+=1;
doc[metrica+'Hosts'].push(incomingHost);
doc.save(function(err){
if(err){
console.log(err);
}
//console.log('Record Updated')
});
}
function insertNewElement(campaignName, newMet, metrica, incomingHost) {
new Order({ name : campaignName, metricCount: newMet }).save(function(err, doc){
if (err) res.json(err);
doc[metrica+'Hosts'].push(incomingHost);
doc.save(function(err){
if(err){
console.log(err);
}
// console.log('new record added '+ doc.name);
});
});
}
我相信在推送新主机时问题仍然存在,因为有很多问题,但是,由于我不是 mongoDB 专家,我不知道如何改进该方法,如果这会导致问题。由于 mongo 文档和研究,我的大部分代码都进行了调整。
如何使更新更快并避免nodejs上的内存错误?
谢谢!