2017-08-07 45 views
0

在S3我已經在這個層次了100M左右(各2.5M)文件:最快的方式EC2 PHP

id_folder/date_folder/hour_file.raw

我試過3點不同的方式來儘快獲取它們:

我開始laravel存儲門面(我使用laravel)..

存儲::盤( 'S3') - >獲取($文件路徑) ; - >這一個是最慢的

然後我google了一點,我發現這個類: Amazon S3的PHP類 http://undesigned.org.za/2007/10/22/amazon-s3-php-class/

我試圖也用有關創建S3Client亞馬遜說明,並使用GetObject函數和它仍然很慢...

所以,我需要從s3獲取大量文件到ec2 - 做到這一點的最快方法是什麼?
Thanx!

+1

S3與EC2之間的聯繫已經很快 – baig772

回答

0

如果我理解你所說的一切,那麼下載許多緩慢的對象就不會有辦法。 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的數據 - 無論您採用何種方式,都需要很長時間。如果您不將文件保存到磁盤,則會快速耗盡內存,那麼您還需要擔心磁盤空間。我不確定爲什麼你需要下載那麼多文件,但它似乎不是一個好主意。