Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 理解节点js中的流_Node.js_Kubernetes_Zipstream_Archiverjs - Fatal编程技术网

Node.js 理解节点js中的流

Node.js 理解节点js中的流,node.js,kubernetes,zipstream,archiverjs,Node.js,Kubernetes,Zipstream,Archiverjs,我遇到了一个问题,需要使用NodeJs创建和下载多个文件的zip文件。 我尝试过但失败的事情: 除此之外,现在文件也被加密了,所以我必须在动态添加到zip之前解密它们 虽然我也解决了这个问题,但当服务器在本地机器上运行时,我的解决方案工作得很好,但在Google Kubernetes引擎上失败了 经过进一步的研究,我想这可能是因为NodeJs中的流中存在背压问题,但正如文档中所述,背压是由管道方法自动处理的。 浏览器的接收速度是否可能与我的服务器/压缩的发送速度不匹配?如果是,如何解决此问

我遇到了一个问题,需要使用NodeJs创建和下载多个文件的zip文件。 我尝试过但失败的事情:

除此之外,现在文件也被加密了,所以我必须在动态添加到zip之前解密它们

虽然我也解决了这个问题,但当服务器在本地机器上运行时,我的解决方案工作得很好,但在Google Kubernetes引擎上失败了

经过进一步的研究,我想这可能是因为NodeJs中的流中存在背压问题,但正如文档中所述,背压是由管道方法自动处理的。 浏览器的接收速度是否可能与我的服务器/压缩的发送速度不匹配?如果是,如何解决此问题

与此问题相关的所有示例都在上面提供的链接中

除此之外,可读流还通过解密对其进行解密

    const handleEntries = ({ elem, uniqueFiles, archive, speedLimit }) => {
  return new Promise((resolve, reject) => {
    let fileName = elem.fileName;
    const url = elem.url;
    const decipher = elem.decipher;
    // changing fileName if same filename is already added to zip
    if (uniqueFiles[fileName] || uniqueFiles[fileName] === 0) {
      uniqueFiles[fileName]++;
    } else {
      uniqueFiles[fileName] = 0;
    }
    if (uniqueFiles[fileName]) {
      const lastDotIndex = fileName.lastIndexOf(".");
      const name = fileName.substring(0, lastDotIndex);
      const extension = fileName.substring(lastDotIndex + 1);
      fileName = `${name}(${uniqueFiles[fileName]}).${extension}`;
    }
    let readableStream = Request(url);
    // create a "Throttle" instance that reads at speedLimit bps
    if (speedLimit) {
      const throttle = new Throttle({ bps: Number(speedLimit) });
      readableStream = readableStream.pipe(throttle);
    }
    // if file is encrypted, need to decrypt it before piping to zip
    readableStream = decipher ? readableStream.pipe(decipher) : readableStream;
    archive.append(readableStream, { name: fileName });
    readableStream.on("complete", result => {
      console.log("Request stream event complete : ", fileName);
      resolve("done");
      // readableStream.unpipe();
      // readableStream.destroy();
    });
    readableStream
      .on("error", error => {
        console.log("Request stream event error fileName : ", fileName, " error : ", error);
        // readableStream.unpipe();
        // readableStream.destroy();
        resolve("done");
      })
      .on("pipe", result => {
        console.log("Request stream event pipe : ", fileName);
      })
      .on("request", result => {
        console.log("Request stream event request : ", fileName);
      })
      .on("response", result => {
        console.log("Request stream event response : ", fileName);
      })
      .on("socket", result => {
        result.setKeepAlive(true);
        console.log("Request stream event socket : ", fileName);
      });
  });
};

const useArchiver = async ({ resp, urls, speedLimit }) => {
  resp.writeHead(200, {
    "Content-Type": "application/zip",
    "Content-Disposition": `attachment; filename="${outputFileName}"`,
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Methods": "GET, POST, OPTIONS"
  });
  const uniqueFiles = {};
  const archive = Archiver("zip", { zlib: 0 });
  archive.pipe(resp);
  archive
    .on("close", result => {
      console.log("archive stream event close : ", result);
      // archive.unpipe();
      // archive.destroy();
    })
    .on("drain", result => {
      console.log("archive stream event drain : ", result);
    })
    .on("entry", result => {
      console.log("archive stream event entry : ", result.stats);
    })
    .on("error", error => {
      console.log("archive stream event error : ", error);
      reject("error");
      // archive.unpipe();
      // archive.destroy();
    })
    .on("finish", result => {
      console.log("archive stream event finish : ", result);
      // archive.unpipe();
      // archive.destroy();
    })
    .on("pipe", result => {
      console.log("archive stream event pipe : ");
    })
    .on("progress", async result => {
      console.log("archive stream event progress : ", result.entries);
      if (urls.length === result.entries.total && urls.length === result.entries.processed) {
        await archive.finalize();
        console.log("finalized : ", urls[0]);
      }
    })
    .on("unpipe", result => {
      console.log("archive stream event unpipe : ");
    })
    .on("warning", result => {
      console.log("archive stream event warning : ", result);
    });
  for (const elem of urls) {
    await handleEntries({ elem, uniqueFiles, archive, speedLimit });
  }
};
我用archiver尝试了这段代码,在压缩大文件时获得archiver的排水事件,管道是否处理背压如果是,为什么我从archiver获得排水事件。

嘿)我研究了你的代码,可以说你使用了承诺函数,你不会等到她完成。您需要使用wait new Promise()包装zipStreamer.entry。一定是这样

async function doSmth() {
   const decipher = crypto.createDecipheriv(
      algorithm,
      Buffer.from(key), 
      Buffer.from(key.substring(0, 9)
   ));
   await new Promise((resolve, reject) => {
     zipStreamer.entry(readableStream.pipe(decipher), {
      name: fileName
     }, (error, result) => {
      if (!error) {
         resolve("done");
      } else {
        reject("error");
      }
     });  
   });
}

似乎我找到了解决方案,我对Kubernetes配置做了一些更改,即将超时时间从30秒增加到300秒,增加CPU限制,并对高达12-13 GB的文件进行了多次测试,效果非常好。
我认为将CPU从.5增加到1并增加超时时间对我来说是可行的

我已经这样做了@Pavel,看看我更新的问题,也可以参考此了解有关该问题的更多信息。嗨@Pavel,谢谢你的贡献,但这个答案是错误的。眼前的问题与承诺无关。@Avius你能在google kubernetes云上与我分享你应用程序的日志吗?他们可以告诉我们问题出在哪里?是的,还是同一个问题,我尝试了很多模块,比如yazl、archiver、zip stream、zipstream,但都表现相同,在本地运行良好,但在google k8s上出现问题,很可能是反压问题。虽然管道本身可以处理背压,但不知道为什么这个问题会持续存在。在这种情况下,我看不出这个问题与您今年早些时候发布的问题(即您故意发布了一个副本)之间有任何显著差异。你也已经知道问题的答案了——操作时间太长,你的进入会切断连接。当然,这在您的本地环境中不是问题,因为您没有该设置。想确定吗?从浏览器向本地服务器发送一个配置了超时的XHR请求,然后查看发生了什么。最后,如果您使用管道和适当的转换流,则背压确实由节点处理。@Avius我也尝试过,在本地更改/配置超时不会做出任何更改,而且超时只是用于初始化响应,一旦浏览器开始接收数据,超时实际上并不重要。关于上一个问题,后来我发现这不是超时问题,即下载有时工作,有时甚至在入口超时增加后也不工作。另外,ingress并没有在固定时间(超时)后完全断开我的连接。这是随机的,文件大小和时间都不相同。当您在本地运行它时,它是直接在主机上运行,还是在docker映像内运行?