上下文:我正在研究使用读取流从SFTP服务器下载文件的代码,并使用Nodejs v10.15.3通过writeStream将其上传到GCS。
由于我工作的SFTP库中的错误,stream.pipe
(即,来自库生成的读取流的管道)实际上在节点10中被破坏,因此,我试图通过以下代码上传此文件(其中stream
是读取流,并且遗漏了不必要的信息):
let acl = fileMode;
if (fileMode === 'public') {
// options for acl are publicRead and private
// need to add the Read if public
acl += 'Read';
}
var options = {
predefinedAcl: acl,
destination: destPath,
metadata: {
contentType: contentType,
cacheControl: 'no-cache'
}
};
// Add in a check here for if the bucket exists
let file = new File(bucket, destPath);
let writeStream = file.createWriteStream(options);
writeStream.on('finish', () => {
file.getMetadata()
.then((metadata) => {
console.log('metadata', metadata);
return resolve(metadata);
})
.catch(error => {
console.error('Error getting file metadata', error);
return reject(error);
});
});
stream.on('end', () => {
try {
writeStream.end();
} catch (err) {
console.error('Error closing writeStream', err);
return reject(err);
}
});
writeStream.on('error', error => {
console.error('Error in writeStream', error);
return reject(error);
});
stream.on('error', error => {
console.error('Error in stream', error);
return reject(error);
});
let data = stream.read();
while (data) {
writeStream.write(data);
data = stream.read();
}
当我使用while (data)
方法从我们的SFTP服务器流式传输到文件系统上的本地文件时,这可以正常工作。但是,当我尝试运行此代码上传到我们的GCS文件时,我收到以下错误:
MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 close listeners added. Use emitter.setMaxListeners() to increase limit
Error in writeStream Error: Retry limit exceeded
// stacktrace omitted
Error Uploading to GCS from a stream: Retry limit exceeded
Error: Retry limit exceeded
看来我在这里做错了,但我不知道为什么这不是一个有效的方法,也不确定我是否缺少一些细微的流(我自己承认它几乎是一个黑盒子me)或GCS的问题。
编辑:好的,这实际上似乎与SFTP问题完全无关。我尝试使用推荐的方法从本地fs上传文件,并看到相同的错误。我正在尝试的“简化”代码更多:
// Add in a check here for if the bucket exists
let file = new File(bucket, destPath);
fs.createReadStream('sample_file.csv')
.pipe(file.createWriteStream(options))
.on('error', function(err) {
console.error('err', err);
return reject(err);
})
.on('finish', function() {
console.log('resolving');
return resolve({gcsUrl: url});
});
正如Alex Riquelme正确指出的那样,当你在Node.js中超过maximum default listeners事件时会发出这个警告。默认情况下,Node.js中事件的最大侦听器数为10.您可以更改此值,但在这种情况下不建议这样做,因为泄漏仍然存在会浪费资源。
为什么要创建多个侦听器以在GCS中上载文件的原因是因为createWriteStream默认启用可恢复上载。在您的情况下,当您上传大量小文件时,建议的方法是将options.resumable
设置为false
。这样,您将避免可恢复上载所导致的开销,而无需允许创建更多侦听器。
实际上预计会出现此警告。当您尝试将文件上传到GCS时,它会尝试优化此上传,并将文件拆分为块(通常以1MB的块为单位)。因此,它将创建多个侦听器来上载此文件。默认情况下,Node.js
中的最大侦听器数量为10
(请查看this documentation)。如果你想将侦听器的数量设置为无限,只需将变量setMaxListeners(0);
设置为0