MST

星途 面试题库

面试题:Node.js 文件复制与移动的高并发处理及优化

在Node.js环境下,假设有一个需求,要同时处理大量文件的复制与移动操作(比如上千个文件)。请设计一个高效的解决方案,考虑高并发场景下的资源竞争、内存管理以及性能优化等问题。详细阐述设计思路,并给出核心代码示例。
47.6万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 高并发控制:使用async/await结合Promise.all来管理并发操作,同时可以通过async - queue这样的库来限制并发数,防止资源竞争导致系统崩溃。
  2. 资源竞争:对文件操作进行加锁处理,避免多个操作同时访问和修改同一文件。在Node.js中,fs模块的同步方法天然是加锁的,但异步方法需要额外处理。可以使用文件系统锁库,如fs - extralock方法来实现。
  3. 内存管理:避免一次性加载大量文件到内存中,采用流(Stream)的方式进行文件复制和移动操作。流可以逐块处理数据,大大减少内存占用。
  4. 性能优化:利用多核CPU的优势,通过cluster模块开启多个工作进程并行处理文件。同时,使用fs模块的异步方法,让I/O操作不阻塞主线程。

核心代码示例

const fs = require('fs');
const path = require('path');
const { promisify } = require('util');
const asyncQueue = require('async - queue');

// 异步的文件复制函数
const copyFileAsync = promisify(fs.copyFile);
// 异步的文件移动函数
const renameAsync = promisify(fs.rename);

// 定义文件操作队列,限制并发数为5
const queue = asyncQueue(async function (task, callback) {
    const { source, destination, isMove } = task;
    try {
        if (isMove) {
            await renameAsync(source, destination);
        } else {
            await copyFileAsync(source, destination);
        }
        callback();
    } catch (err) {
        console.error(`操作 ${source} 到 ${destination} 失败:`, err);
        callback(err);
    }
}, 5);

// 生成任务列表
function generateTasks(files, sourceDir, targetDir, isMove) {
    return files.map(file => {
        const source = path.join(sourceDir, file);
        const destination = path.join(targetDir, file);
        return { source, destination, isMove };
    });
}

// 主函数
async function main() {
    const sourceDir = 'path/to/source';
    const targetDir = 'path/to/target';
    const files = fs.readdirSync(sourceDir);
    const tasks = generateTasks(files, sourceDir, targetDir, false); // false表示复制操作,true表示移动操作

    tasks.forEach(task => queue.push(task));

    return new Promise((resolve, reject) => {
        queue.drain = function () {
            resolve();
        };
        queue.error = function (err) {
            reject(err);
        };
    });
}

main().then(() => {
    console.log('所有文件操作完成');
}).catch(err => {
    console.error('操作过程中出现错误:', err);
});