我有一个内置Express 3.20的应用程序。我继续保持并运行PM2。观察PM2中的内存使用情况,我发现每个进程只需要几个小时的使用时间就会变成> 500MB,此时就会出现问题。
我的应用收到的约90%的请求都是针对缩略图。所以我猜测内存泄漏来自我向用户提供缩略图的代码部分。
代码的工作方式,用户请求特定大小的图像。脚本检查缓存/文件夹中是否已存在该大小的图像。如果是这样,它会将该文件发送给客户端。如果没有,它使用graphicsMagick从原始图像在缓存/文件夹中创建一个新图像,然后发送它。
我在下面提供相关代码。任何人都可以告诉我,如果我在这里做任何明显错误的事情,那会导致事情在内存中流传吗?
先谢谢你的帮助。
var fs = require( "graceful-fs" ),
gm = require( "gm" );
function isOriginalNewer( orig, cache ) {
return orig.ctime > cache.ctime ? true : false;
}
function checkIfCachedImageUpToDate( originalPath, cachePath, cb ) {
fs.stat( originalPath, function( err, stat1 ) {
if ( err ) return cb( err );
fs.stat( cachePath, function( err, stat2 ) {
if ( err ) return cb( err );
if ( isOriginalNewer( stat1, stat2 ) ) {
cb ( null, false );
} else {
cb( null, true );
}
});
});
}
function createNewCachedImage( originalPath, cachePath, cacheSubDir, size, cb ) {
fs.exists( "cache/" + cacheSubDir, function ( exists ) {
if ( exists ) {
gm( originalPath ).resize( size, null, "^" ).quality( 95 ).write( cachePath, cb );
} else {
fs.mkdir( "resources/cache/" + cacheSubDir, 0750, function() {
gm( originalPath ).resize( size, null, "^" ).quality( 95 ).write( cachePath, cb );
});
}
});
}
function checkIfCached( originalPath, cachePath, cb ) {
fs.exists( cachePath, function( exists ){
if ( exists ) {
checkIfCachedImageUpToDate( originalPath, cachePath, function( err, isUpToDate ) {
if ( err ) return cb( err );
if ( isUpToDate ) cb( null, true );
else cb( null, false );
});
} else cb( null, false );
});
}
function getImagePath( filename, type, size, cb ) {
var originalPath = "originals/" + filename,
cacheFilename = hash.md5( originalPath ) + "." + size + ".jpg",
cacheSubDir = cacheFilename.substr( 0,2 ),
cachePath = "cache/" + cacheSubDir + "/" + cacheFilename;
checkIfCached( originalPath, cachePath, function( err, isCached ) {
if ( err ) return cb( err );
if ( isCached ) {
cb( null, cachePath );
} else {
fs.exists( originalPath, function( exists ) {
if ( !exists ) return cb( "File Not Found " + originalPath );
createNewCachedImage( originalPath, cachePath, cacheSubDir, size, function( err ) {
if ( err ) return cb( err );
cb( null, cachePath );
});
});
}
});
}
module.exports = function( app ){
app.get( "/image/:filename/:size", isLoggedIn, function( req, res, next ){
var p = sanitizeParams( req );
getImagePath( p.filename, p.size, function( err, imagePath ){
if ( err ) next( err );
else res.sendfile( imagePath );
});
});
};