Google Cloud Bucket 文件下载 (NodeJS)。文件存在但可读会引发错误并使 Express 服务器重新启动

问题描述 投票:0回答:1

在我们使用

@google-cloud/storage
的快递服务器中,在某些情况下,当通过可读流从我们的存储桶下载文件时,甚至订阅流中的.error(不会被调用),我会收到错误,即使这样调用被包装到一个 try-catch 中,我们的express实例重新启动,没有杀死pod而是重新启动express本身,非常奇怪。

我从 Express 日志中得到的错误如下所示:

TypeError: Cannot read properties of null (reading 'length')
    at getStateLength (/usr/src/node_modules/stream-shift/index.js:16:28)
    at shift (/usr/src/node_modules/stream-shift/index.js:6:99)
    at Duplexify._forward (/usr/src/node_modules/duplexify/index.js:170:35)
    at PassThrough.onreadable (/usr/src/node_modules/duplexify/index.js:136:10)
    at PassThrough.emit (node:events:518:28)
    at emitReadable_ (node:internal/streams/readable:832:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:81:21)

我得到另一条痕迹,表明它在此时爆炸了:

return state.buffer[0].length

这似乎对应于流移位代码的这一部分: https://github.com/mafintosh/stream-shift/blob/2ea5f7dcd8ac6babb08324e6e603a3269252a2c4/index.js#L16C1-L16C34

我的下载代码如下所示:

  const { bucketName, keyFilename } = config.google.storage;
  if (!bucketName) {
    throw badImplementation('config.google.storage.bucketName is undefined');
  }
  if (!keyFilename) {
    throw badImplementation('config.google.storage.keyFilename is undefined');
  }

  const storage = new Storage({
    keyFilename,
    retryOptions: { autoRetry: true, maxRetries: 1 },
  });
  const bucket = storage.bucket(bucketName);

  const [exists] = await bucket.file(name).exists();
  if (!exists) {
    const error = `CDN download, file ${name} does not exist`;
    console.log(error);
    throw notFound(error);
  }

  log.info(`CDN download, create read stream on ${name} begin`);
  const readStream = bucket
    .file(name)
    .createReadStream()
    .on('response', (response) => {
      // Server connected and responded with the specified status and headers.
      console.log(`CDN download, stream on file ${name}, response is: ${JSON.stringify(response)}`);
    })
    .on('end', () => {
      // The file is fully downloaded.
      console.log(`CDN download, stream on file ${name}, file fully downloaded`);
    })
    .on('error', (err) => {
      // Something happened while downloading the file
      console.log(`CDN download, stream on file ${name}, error is: ${JSON.stringify(err)}`);
    });

  log.info(`CDN download, create read stream on ${name} done`);
  return readStream;

我认为该文件不可能存在,但我添加了 .exists() 的检查,它返回 true,因此创建了 readStream()。

我什至从识别文件的

.on('response'
部分得到了痕迹。

{
  "headers": {
    "cache-control": "no-cache, no-store, max-age=0, must-revalidate",
    "content-disposition": "attachment",
    "content-length": "1309467",
    "content-type": "application/octet-stream",
    "date": "Wed, 24 Jan 2024 11:17:05 GMT",
    "etag": "CLSOmpWa8oMDEAE=",
    "expires": "Mon, 01 Jan 1990 00:00:00 GMT",
    "last-modified": "Tue, 23 Jan 2024 00:00:33 GMT",
    "pragma": "no-cache",
    "server": "UploadServer",
    "vary": "Origin, X-Origin",
    "x-goog-generation": "1705968033761076",
    "x-goog-hash": "crc32c=EeUAng==,md5=Duc9MjxstOaEXhEeZRphIw==",
    "x-goog-metageneration": "1",
    "x-goog-storage-class": "STANDARD",
    "x-goog-stored-content-encoding": "identity",
    "x-goog-stored-content-length": "1309467",
    "x-guploader-uploadid": "ABPtcPpJ0EZifzef-2dHFzbfURL0E_niJIylxjegZyJhjJ0kyhM8FGb7jymom35PJ4UrOcti3mp8CxNuqw"
  }
}

是否即使客户端检查说文件存在,我们也没有下载该文件的权限?

更新 1:经过进一步调查并回滚我们的 docker 镜像,我们发现在 1 月 9 日到 1 月 11 日之间,我们的基础镜像 Node:20 推送了一个更改,这似乎是问题所在:https://github.com/nodejs/docker -节点/提交/ab5769dc69feb4007d9aafb03316ea0e3edb4227

这从节点 20.10 更改为 20.11,这是发生类似情况的唯一可能的解释,是否报告了任何已知问题?

更新2:从 docker 镜像节点:20 到节点:20.10.0 的解决方法解决了该问题,节点:20.11.0(又名最新)中必须引入了某些内容,来自节点或谷歌的任何人都可以调查发生了什么吗?

node.js express google-cloud-storage google-bucket
1个回答
0
投票

根据 此 GitHub 评论线程,除了降级到 Node

20.11.0
之外,您还可以使用 package override 来使用
stream-shift
版本
1.0.2
,这应该可以解决此问题。

希望它也能尽快在

@google-cloud/storage
包中更新。

© www.soinside.com 2019 - 2024. All rights reserved.