如果我理解你所說的一切,那麼下載許多緩慢的對象就不會有辦法。 100,000,000 * 2.5MB = 250TB。這是很多數據。儘管如此,你可以做些事情來提高效率。
如果您試圖通過使用S3\Client::getObjects
同步下載這些對象來「立即」獲取很多(即數千個)對象,則需要花費很長時間。通過使用S3\Client::getObjectsAsync
可以得到更快一點,它將返回Guzzle\Promise\Promise
。這不是非同步的。所有對S3的請求不會同時執行。無論如何,調用getObjectsAsync
都會阻塞該線程,直到請求完成。只需循環遍歷一個循環,並調用Guzzle\Promise\Promise::wait
仍然會持續。
但是,如果您分解您的請求並同時批量執行它們,您可以從請求中刪除一些重要時間。 Guzzle提供了一個few options來等待承諾數組,但我更喜歡Guzzle\Promise\unwrap
函數。它返回給定的promise數組結果數組。
下面是一臺發電機我寫的做到了這一點:
public function getObjectsBatch($bucket, $keys, $chunkSize = 350)
{
foreach (array_chunk($keys, $chunkSize) as $chunk) {
$promises = [];
foreach ($chunk as $key) {
$promises[] = $this->getClient()->getObjectAsync([
'Bucket' => $bucket,
'Key' => $key
])->then($success = function (Result $res) use ($key) {
$res->offsetSet('Key', $key);
return $res;
}, $fail = function (S3Exception $res) {
return $res;
});
}
yield unwrap($promises);
}
}
我用這個來下載上千對象,並將其流式傳輸到用戶,因爲他們下載。
批次的大小很重要。在這個例子中,我一次執行350個請求。我做了一些測試,這似乎是最有效的。在我的測試中,我使用各種批量大小從S3下載了4500個對象。我爲每個批量大小執行了10次測試。 350似乎是最有效的。
但是,您的具體使用案例 - 一次下載250TB的數據 - 無論您採用何種方式,都需要很長時間。如果您不將文件保存到磁盤,則會快速耗盡內存,那麼您還需要擔心磁盤空間。我不確定爲什麼你需要下載那麼多文件,但它似乎不是一個好主意。
S3與EC2之間的聯繫已經很快 – baig772