【问题标题】:Retry limit exceeded when uploading file上传文件时超出重试限制
【发布时间】:2019-05-07 21:44:47
【问题描述】:

上下文:我正在编写代码,该代码使用读取流从 SFTP 服务器下载文件并通过 writeStream 将其上传到 GCS,使用 Nodejs v10.15.3。

由于我正在使用的 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

似乎我在这里一定做错了什么,但我不知道为什么这不是一个有效的方法,我也不确定我是否错过了一些微妙的流(我坦白承认这几乎是对我来说是黑匣子)或 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});
    });

【问题讨论】:

  • 你在哪里运行你的代码?是 App Engine、Cloud Function、Cloud Run、Compute VM Instance 还是 Google Cloud 之外的服务器?
  • 此错误:从流上传到 GCS:超出重试限制由客户端库升级:对于发生 5 次以上的错误 404 或当指数回退失败超过 5 次时从 499 到 600 .
  • 现在它通过 Google Cloud 外部的本地 docker 设置运行,这是我们在部署服务之前在本地开发和测试服务的地方。
  • 您是否为存储桶正确配置了 CORS?您是否将您的用户/服务帐户配置为对存储桶具有写入权限?您能否通过您使用的配置验证使用 gsutil(Could SDK)上传是否有效?
  • 这三个问题的答案都应该是肯定的。值得注意的是bucket.exists 可以工作,等等。

标签: javascript node.js google-cloud-storage


【解决方案1】:

正如 Alex Riquelme 正确指出的那样,当您在 Node.js 中超过 maximum default listeners 的事件时,会发生此警告。默认情况下,Node.js 中事件的最大侦听器数量为 10。您可以更改此值,但是在这种情况下不建议这样做,因为这会浪费资源,因为泄漏仍然存在。

之所以要创建多个侦听器来上传 GCS 中的文件,是因为createWriteStream 中默认启用了可恢复上传。在您的情况下,当您上传大量小文件时,推荐的方法是将options.resumable 设置为false。这样您就可以避免由可恢复上传造成的开销,而无需创建更多侦听器。

【讨论】:

    【解决方案2】:

    这个警告实际上是预期的。当您尝试将文件上传到 GCS 时,它会尝试优化此上传并将您的文件分割成块(通常为 1MB 的块)。因此,它将创建多个侦听器来上传此文件。默认情况下,Node.js 中的最大侦听器数量为10(查看this documentation)。如果要将侦听器的数量设置为无限制,只需将变量 setMaxListeners(0); 设置为 0

    【讨论】:

    • 人力资源部。两个问题... 1. 我到底应该调用 setMaxListeners 什么?我已经尝试了stream.setMaxListeners(0);writeStream.setMaxListeners(0);,但仍然收到“检测到可能的 EventEmitter 内存泄漏”错误。 2. 对于一个 7kB 的文件,这似乎有过多的侦听器......真的正确吗?
    • 1.在this SO 问题中,您会发现许多使用emitter.setMaxListeners() 的方法。但是,这似乎不是推荐的方法,因为您最终可能会隐藏可能的内存泄漏。
    • 2.是的,7kb 文件的监听器似乎很多,您可以考虑将options.resumable 设置为false,因为createWriteStream 自动启用可恢复上传,这可能会在上传小文件时导致性能下降。
    • @dhauptman 谢谢,将 options.resumable 设置为 false 已修复!如果使用该建议编辑了此答案,或者发布了新答案,我将继续并使其成为已接受的答案。
    • 不客气 :))我已经发布了一个新的答案。
    猜你喜欢
    • 2014-08-20
    • 2012-06-06
    • 2012-12-31
    • 2015-02-27
    • 2018-01-30
    • 2012-08-08
    • 2013-01-12
    • 1970-01-01
    • 2017-08-22
    相关资源
    最近更新 更多