本文介绍: 通过一个 RangeError: Array buffer allocation failed错误,认识到了内存合理使用的重要性。解决这个问题我们的大文件分片上传功能运行更加稳定。如果你有更高明的方法,欢迎到评论讨论文章首发于IICOOM-个人博客 《RangeError: Array buffer allocation failed》…

使用 Node.js 合并文件分片出现标题错误信息

代码分析

m.merge = (opts) => {
  return new Promise((resolve, reject) => {
    const { filename, target } = opts;
    try {
      let len = 0;
      const bufferList = fs.readdirSync(`${STATIC_TEMPORARY}/${filename}`).map((hash, index) => {
        const buffer = fs.readFileSync(`${STATIC_TEMPORARY}/${filename}/${index}`);
        len += buffer.length;
        return buffer;
      });
      // Merge files
      const buffer = Buffer.concat(bufferList, len);
      const ws = fs.createWriteStream(`${target}/${filename}`);
      ws.write(buffer);
      ws.close();
      resolve({ success: true, msg: 'Section merge completed' });
    } catch (error) {
      console.error(error);
      reject({ success: false, msg: error });
    }
  });
};

const buffer = Buffer.concat(bufferList, len);
定位到是上边这行出现问题检查了一下服务器node应用内存占用是 192.1mb

这时原因就很明了,是因为文件分片太大导致内存耗尽,没有可用空间了。

优化方法

上面的做法是把所有的文件分片concat然后写到流中,正是在这个过程中导致了内存耗尽。
其实我们可以顺序多次concat写入修改代码如下

m.merge = (opts) => {
  return new Promise((resolve, reject) => {
    const { filename, target } = opts;

    try {
      // 优化
      const ws = fs.createWriteStream(`${target}/${filename}`);
      const bufferList = fs.readdirSync(`${STATIC_TEMPORARY}/${filename}`)
      let len = 0;
      let list = []
      bufferList.forEach((hash, index) => {
        const b = fs.readFileSync(`${STATIC_TEMPORARY}/${filename}/${index}`);
        len += b.length;
        list.push(b)
        if (len > 10485760) { // 10M
          const buffer = Buffer.concat(list, len);
          ws.write(buffer);
          len = 0;
          list = []
        }
      })
      ws.close();
      resolve({ success: true, msg: 'Section merge completed' });
    } catch (error) {
      console.error(error);
      reject({ success: false, msg: error });
    }
  });
};

这是重新调用接口就不会出现标题错误了,文件可以合并成功。但是查看一下Node进程内存占用 却仍然保持在192.1mb左右。

如果,再分析一下,上边的代码还是有些啰嗦,尝试下面的写法

m.merge = (opts) => {
  return new Promise((resolve, reject) => {
    const { filename, target } = opts;
    try {
      // 优化
      const ws = fs.createWriteStream(`${target}/${filename}`);
      const bufferList = fs.readdirSync(`${STATIC_TEMPORARY}/${filename}`)
      bufferList.forEach((hash, index) => {
        const b = fs.readFileSync(`${STATIC_TEMPORARY}/${filename}/${index}`);
        ws.write(b);
      })
      ws.close();
      resolve({ success: true, msg: 'Section merge completed' });
    } catch (error) {
      console.error(error);
      reject({ success: false, msg: error });
    }
  });
};

直接读取到的文件写入ws,因为文件大小已经被分片为1M大小,每次读取完写入到ws后就会被Node.js 的GC回收,理论上是比较安全操作

修改完毕,经过测试发现,只有在文件上传合并分片时候有200M左右的内存占用和较高的CPU消耗,合并完成后就趋于平稳。

在这里插入图片描述

总结

通过一个 RangeError: Array buffer allocation failed错误,认识到了内存合理使用的重要性。解决这个问题我们的大文件分片上传功能运行更加稳定

如果你也遇到了这样的问题,希望本文可以帮助到你,还请帮忙点个赞❤️❤️,谢谢。如果你有更高明的方法,欢迎到评论讨论

文章首发于 IICOOM-个人博客|技术博客 《RangeError: Array buffer allocation failed》

原文地址:https://blog.csdn.net/IICOOM/article/details/126596918

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_42704.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注