我有一个聊天应用程序,用户发送文件给对方。每个文件必须在2天后删除。
为此,我每4小时递归检查一次所有文件,并删除那些创建时间超过2天的文件。
但这项工作消耗了我的服务器的CPU,这扰乱了应用程序的工作。因为要检查的文件数量非常大,所有文件的大小约为10 GB。
现在,如果每个文件一上传,一个计时器就被激活,在2天后删除该文件,这是更好的吗?考虑到几乎每秒上传一个文件,计时器的数量可能非常高。
我的递归解决方案:
const fs = require('fs')
const path = require('path')
const rootDir = require('../config').rootDir
const log = require('../da/log');
const DIRECTORY_MESSAGES = rootDir + '/file/messages';
const DIRECTORY_AVATARS = rootDir + '/file/avatars';
const INTERVAL_MINUTES_MESSAGES = 240;
const INTERVAL_MINUTES_AVATARS = 265;
const ACCESS_DAYS_MESSAGES = 2;
const ACCESS_DAYS_AVATARS = 10;
/*
* Remove files that access times is older than {fileAccessHours}.
* Runs every {removeEveryMinutes}
* */
module.exports = {
start: function () {
setInterval(deleteFiles.bind(this, DIRECTORY_MESSAGES, ACCESS_DAYS_MESSAGES), INTERVAL_MINUTES_MESSAGES * 60_000)
setInterval(deleteFiles.bind(this, DIRECTORY_AVATARS, ACCESS_DAYS_AVATARS), INTERVAL_MINUTES_AVATARS * 60_000)
}
}
function deleteFiles(dir, accessDays) {
walkDir(dir, function (path, isDirectory) {
try {
if (isDirectory) {
if (path === dir) {
return;
}
return fs.rmdir(path, function (err) {
if (err) {
return log.error(__filename + ' :deleteFiles, fs.rmdir, ' + err);
}
});
} else {
fs.stat(path, function (err, stat) {
try {
const now = new Date().getTime();
const endTime = new Date(stat.atime).getTime() + accessDays * 86_400_000;
if (err) {
return log.error(__filename + ' :deleteFiles, fs.stat, ' + err);
}
if (now > endTime) {
return fs.unlink(path, function (err) {
if (err) {
return log.error(__filename + ' :deleteFiles, fs.unlink, ' + err);
}
});
}
} catch (err) {
console.log('File Deleter: walkDir: callback: fs.stat: ' + err);
}
});
}
} catch (err) {
console.log('File Deleter: walkDir: callback' + err);
}
});
}
function walkDir(dir, callback) {
try {
let files = fs.readdirSync(dir);
if (files.length === 0) {
callback(dir, /* isDirectory */ true);
} else {
files.forEach(f => {
let dirPath = path.join(dir, f);
let isDirectory = fs.statSync(dirPath).isDirectory();
isDirectory ? walkDir(dirPath, callback) : callback(path.join(dir, f), /* isDirectory */ false);
});
}
} catch (err) {
console.log('File Deleter: walkDir: ' + err);
}
}
字符串
3条答案
按热度按时间x7rlezfr1#
现在,如果每个文件一上传,一个计时器就被激活,在2天后删除该文件,这是更好吗?
“更好”是一个不确定的概念,但是考虑一下如果服务器崩溃并重新启动,或者您必须关闭它来升级等情况会发生什么:这些计时器丢失了,您必须再次执行目录遍历。
这看起来像是一个简单数据库的应用程序,它可以是一个由文件支持的进程内数据库(比如
sqlite
数据库),或者现在,让一个合适的数据库进程运行起来也很简单。你在上传时记录文件的日期/时间和路径,然后定期查询数据库,查看哪些文件已经过期,需要删除。不需要目录遍历。如果使用单独的数据库,(而不是进程内),清理甚至可以像A R K建议的那样是一个单独的进程,而不是捆绑服务器的主Node.js线程。14ifxucb2#
做目录walkkm但不要重新发明轮子。例如使用gnu find:
字符串
从cron上运行。
wqnecbli3#
我会创建一个“”对象的矢量:
字符串
在上传的每个文件上,向vector的Back添加一个对象,并将vector存储在文件中以进行持久化(崩溃/重启场景)。
一个“Deleter”工作线程,它会休眠直到必须删除向量的Front项,然后进入休眠状态,直到删除下一个项。
重启时:“Deleter”工作线程从文件中加载vector,从vector的Front中删除所有已经过期并进入睡眠状态的项,直到必须删除当前Front为止。