在我们使用
@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(又名最新)中必须引入了某些内容,来自节点或谷歌的任何人都可以调查发生了什么吗?
根据 此 GitHub 评论线程,除了降级到 Node
20.11.0
之外,您还可以使用 package override 来使用 stream-shift
版本 1.0.2
,这应该可以解决此问题。
希望它也能尽快在
@google-cloud/storage
包中更新。