【发布时间】:2019-08-21 12:19:06
【问题描述】:
AWS S3 文档状态 (https://docs.aws.amazon.com/AmazonS3/latest/dev/request-rate-perf-considerations.html):
Amazon S3 自动扩展到高请求率。例如,您的应用程序在存储桶中的每个前缀每秒可以实现至少 3,500 个 PUT/POST/DELETE 和 5,500 个 GET 请求。
为了测试这一点,我有以下 NodeJS 代码(使用 aws-sdk),它异步启动 1000 次零字节上传(因此,只需将空条目添加到存储桶中)。有一个计时器可以测量吞吐量:
var t0 = new Date().getTime()
for (var i = 0; i < 1000; i++) {
var s3 = new AWS.S3()
var id = uuid()
console.log('Uploading ' + id)
s3.upload({
Bucket: bucket,
Body : '',
Key : "test/" + id
},
function (err, data) {
if (data) console.log('Uploaded ' + id + ' ' + (new Date().getTime() - t0))
else console.log('Error')
})
}
完成所有上传请求大约需要 25 秒。这显然与声称的每秒 3500 个请求相去甚远,而是大约每秒 40 个请求。
我有大约 1MB 的网络上传速度,网络统计数据显示,在大多数情况下,带宽只有大约 25% 饱和。同样,CPU 利用率也很低。
所以问题是:
如何扩展 S3 上传吞吐量以实现接近每秒 3500 个请求的速度?
编辑:
我这样修改代码:
var t0 = new Date().getTime()
for (var i = 0; i < 1000; i++) {
var s3 = new AWS.S3()
var id = String.fromCharCode('a'.charCodeAt(0) + (i % 26)) + uuid()
console.log('Uploading ' + id)
s3.upload({
Bucket: bucket,
Body: '',
Key: id
},
function (err, data) {
if (data) console.log('Uploaded ' + id + ' ' + (new Date().getTime() - t0))
else console.log('Error')
})
}
这使用了 26 个不同的前缀,AWS 文档声称它们应该将吞吐量扩大 26 倍。
“以指数方式提高读取或写入性能很简单。例如,如果您在 Amazon S3 存储桶中创建 10 个前缀来并行读取,则可以将读取性能扩展到每秒 55,000 个读取请求。”
但是,吞吐量没有明显差异。行为存在某种差异,因此请求似乎以更并行的方式完成,而不是按顺序完成 - 但完成时间几乎相同。
最后,我尝试在 x4 个单独的 bash 线程(4 个线程、4 个内核、4x1000 个请求)中运行应用程序。尽管使用多核增加了并行性,但总执行时间约为 80 秒,因此无法扩展。
for i in {0..3}; do node index.js & done
我想知道 S3 是否会限制单个客户端/IP(尽管这似乎没有记录在案)?
【问题讨论】:
-
您的代码在哪里运行?如果您在与您调用的 S3 端点位于同一区域的 EC2 主机上运行它(以排除您和 AWS 之间的任何瓶颈),看看您会得到什么会很有趣。另外——我注意到您正在为每个请求创建一个单独的
AWS.S3实例。我对 Node AWS SDK 不是很熟悉,但我的直觉认为那是不必要的昂贵,并且您可以通过创建单个实例、使用同步请求“预热”然后进行 1000 来获得更好的性能实际测试的异步请求。 -
它在我的家庭网络上的本地机器上运行。我可以在大约 2 秒内启动所有 1000 个请求,因此 S3 实例不是我认为的瓶颈(另外,如果您使用单个实例,SDK 会警告过多的侦听器)。它似乎是 S3 方面的东西。不过,在 EC2 实例上尝试它会很有趣。
-
有时,所有上传都在大约 25 秒内完成,最后一小部分需要大约 70 秒才能完成。就好像 S3 正在重新平衡最后几个索引或其他东西。
-
您的应用程序是单线程的。这不是对访问 S3 的成百上千用户的真实模拟。您的模拟应该从多个来源运行并行测试以获得真正的测量。您是否真的有需要这种吞吐量的应用程序,或者您只是将其作为学术练习?
-
我有一个应用程序。这是一个在线备份应用程序,可以直接从用户的机器将数百万个小对象添加到 S3。所以吞吐量是个问题。是的,它是单线程的,但它也是异步的,大部分时间都花在等待网络响应上,这意味着 CPU 负载并不是真正的问题。
标签: node.js amazon-web-services amazon-s3