Node.js 当mongoose模型被实例化时,应用程序速度会减慢
作为学习的一部分,我正在开发购物车。我面临的问题是,无论何时将项目添加到购物车,装载时间都会显著增加(下面的基准测试),当购物车为空时,装载时间会恢复正常Node.js 当mongoose模型被实例化时,应用程序速度会减慢,node.js,mongodb,express,mongoose,Node.js,Mongodb,Express,Mongoose,作为学习的一部分,我正在开发购物车。我面临的问题是,无论何时将项目添加到购物车,装载时间都会显著增加(下面的基准测试),当购物车为空时,装载时间会恢复正常 基准 当购物车为空时:装载时间小于1s GET / 304 154.242 ms - - GET /stylesheets/bootstrap.css 304 81.079 ms - - GET /stylesheets/style.css 304 79.363 ms - - GET /fonts/font-awesome/css/font
基准
当购物车为空时:装载时间小于1s
GET / 304 154.242 ms - -
GET /stylesheets/bootstrap.css 304 81.079 ms - -
GET /stylesheets/style.css 304 79.363 ms - -
GET /fonts/font-awesome/css/font-awesome.min.css 304 84.550 ms - -
GET /product/58c179fb2148643f5865d4ca/image 304 86.347 ms - -
GET /product/58c151f95b18373990f1c714/image 304 113.943 ms - -
GET /product/58c17c9e32f18e2eb86fbd44/image 304 120.220 ms - -
GET /product/58c17ced9697ec3e44bba381/image 304 82.483 ms - -
GET /product/58c210c5e5ca5b2298724b77/image 304 83.583 ms - -
GET /fonts/font-awesome/fonts/fontawesome-webfont.woff2?v=4.7.0 304 15.826 ms - -
当物品在购物车中时:装载时间平均为10秒
GET / 304 3441.581 ms - -
GET /stylesheets/bootstrap.css 304 17074.679 ms - -
GET /stylesheets/style.css 304 18020.767 ms - -
GET /fonts/font-awesome/css/font-awesome.min.css 304 19067.181 ms - -
GET /product/58c17c9e32f18e2eb86fbd44/image 304 13065.619 ms - -
GET /product/58c151f95b18373990f1c714/image 304 15917.767 ms - -
GET /product/58c179fb2148643f5865d4ca/image 304 22550.998 ms - -
GET /product/58c17ced9697ec3e44bba381/image 304 23376.352 ms - -
GET /product/58c210c5e5ca5b2298724b77/image 304 20143.963 ms - -
GET /fonts/font-awesome/fonts/fontawesome-webfont.woff2?v=4.7.0 304 4767.430 ms - -
下面的代码是最低限度的实现: models/product.js
var schema = new Schema({
image: {data: Buffer, contentType: String},
title: {type: String, required: true},
description: {type: String, required: true},
price: {type: Number, required: true}
});
module.exports = mongoose.model('Product', schema);
module.exports = function Cart(oldCart) {
// associative array
this.items = oldCart.items || {};
this.add = function(product) {
// if item is not in cart => assign argument to product properties
if(!this.items[product._id])
this.items[product._id] = {product: product, qty: 0, price: 0};
// if item is already in cart => just increase the qty and price
this.items[product._id].qty++;
this.items[product._id].price += product.price;
}
this.removeItems = function (productId) {
delete this.items[productId];
}
}
router.get('/add-to-cart/:id', function (req, res, next) {
var productId = req.params.id;
// req.session from: express-session module
var cart = new Cart(req.session.cart);
Product.findById(productId, function (err, product) {
cart.add(product);
req.session.cart = cart;
res.redirect('/');
});
});
router.get('/remove/:id', function (req, res, next) {
var productId = req.params.id;
var cart = new Cart(req.session.cart);
cart.removeItems(productId);
req.session.cart = cart;
res.redirect('/cart');
});
模型/cart.js
var schema = new Schema({
image: {data: Buffer, contentType: String},
title: {type: String, required: true},
description: {type: String, required: true},
price: {type: Number, required: true}
});
module.exports = mongoose.model('Product', schema);
module.exports = function Cart(oldCart) {
// associative array
this.items = oldCart.items || {};
this.add = function(product) {
// if item is not in cart => assign argument to product properties
if(!this.items[product._id])
this.items[product._id] = {product: product, qty: 0, price: 0};
// if item is already in cart => just increase the qty and price
this.items[product._id].qty++;
this.items[product._id].price += product.price;
}
this.removeItems = function (productId) {
delete this.items[productId];
}
}
router.get('/add-to-cart/:id', function (req, res, next) {
var productId = req.params.id;
// req.session from: express-session module
var cart = new Cart(req.session.cart);
Product.findById(productId, function (err, product) {
cart.add(product);
req.session.cart = cart;
res.redirect('/');
});
});
router.get('/remove/:id', function (req, res, next) {
var productId = req.params.id;
var cart = new Cart(req.session.cart);
cart.removeItems(productId);
req.session.cart = cart;
res.redirect('/cart');
});
路线/cart.js
var schema = new Schema({
image: {data: Buffer, contentType: String},
title: {type: String, required: true},
description: {type: String, required: true},
price: {type: Number, required: true}
});
module.exports = mongoose.model('Product', schema);
module.exports = function Cart(oldCart) {
// associative array
this.items = oldCart.items || {};
this.add = function(product) {
// if item is not in cart => assign argument to product properties
if(!this.items[product._id])
this.items[product._id] = {product: product, qty: 0, price: 0};
// if item is already in cart => just increase the qty and price
this.items[product._id].qty++;
this.items[product._id].price += product.price;
}
this.removeItems = function (productId) {
delete this.items[productId];
}
}
router.get('/add-to-cart/:id', function (req, res, next) {
var productId = req.params.id;
// req.session from: express-session module
var cart = new Cart(req.session.cart);
Product.findById(productId, function (err, product) {
cart.add(product);
req.session.cart = cart;
res.redirect('/');
});
});
router.get('/remove/:id', function (req, res, next) {
var productId = req.params.id;
var cart = new Cart(req.session.cart);
cart.removeItems(productId);
req.session.cart = cart;
res.redirect('/cart');
});
尝试:
我曾试图将不需要的对象设置为
null
,我猜想内存可能会泄漏到某个地方。问题仍然存在
产品图像不超过16MB,所以我将它们作为二进制数据存储在mongo中。我真的不知道加载时间是如何增加的。感谢您的每一个建议。我愿意编辑这篇文章以提供更多信息。您的问题可能是由于您在按id查找产品时加载了图像缓冲区造成的
...
image: {data: Buffer, contentType: String},
...
由于添加到购物车时不需要这些信息,请在find by id上告诉mongo不要返回该字段
Product.findById(productId).select('-image').exec(function(){})
然后,当有人看到他们的购物车时,可能会再次调用检索图像
编辑:
确保在检索图像时也在缓存图像。这将确保您的服务器能够快速提供图像
你看,它应该能满足你的需要
在客户端,您可能需要确保您的图像也被缓存在那里(这可能已经自动发生)
编辑2:
我相信像这样的东西应该对你的心尖痛有效。你可能需要稍微调整一下
var apicache = require('apicache');
let cache = apicache.middleware;
...
app.get('/image/:productId', cache('1 hour'), function(req, response) {
var buffer = ""; //get the image buffer from mongo
//return to client
response.writeHead(200, {
'Content-Type': 'image/jpeg' //Or whatever filetype its supposed to be... png, gif etc
});
response.write(buffer);
response.end();
});
...
我尝试了你的建议,它解决了我的问题。我的另一个疑问是,如果是因为加载了缓冲区,那么只有涉及购物车的请求/代码(即添加到卡和视图购物车)才会减慢速度。然而,问题是,每当购物车中有物品时,整个应用程序的加载时间就会增加,包括主页、登录、注册等。@NERDYLIZARD我认为整个应用程序的速度很慢,因为您将图像缓冲区存储在会话变量中,每次应用程序重新加载时,都必须再次加载整个图像缓冲区。只是一个想法。可能是错的。也许在确认你没有在那里存储数据后,可以尝试清除你的会话。@NERDYLIZARD哇哇。我现在明白你的意思了。也许可以看看是否有办法为客户端缓存该图像信息,这样他们只需要加载一次图像。你的服务器端抓取图像的路线,可以做缓存,我看了一下文档。我应该把缓存放在哪里?@NERDYLIZARD如果你把这个答案标记为解决方案,会非常感激的如果你需要其他帮助。让我知道!