2015-02-22 13 views
5

Công ty của tôi đang tải lên các tệp lưu trữ lớn lên S3 và bây giờ muốn chúng được giải nén trên S3. Tôi đã viết một hàm lambda dựa trên giải nén, được kích hoạt bằng cách đưa tệp vào nhóm xxx-zip, luồng tệp zip từ S3, giải nén luồng và sau đó truyền các tệp riêng lẻ vào nhóm dữ liệu xxx.sử dụng hàm lambda để giải nén lưu trữ trong S3 thực sự là sloooooow

Nó hoạt động, nhưng tôi thấy nó chậm hơn nhiều so với mong đợi - ngay cả trên tệp thử nghiệm, kích thước zip khoảng 500k và giữ khoảng 500 tệp, đây là thời gian hết hạn với 60 giây. Điều này có vẻ đúng không? Trên hệ thống cục bộ của tôi đang chạy với nút, nó nhanh hơn điều này. Dường như với tôi rằng vì các tệp đang được di chuyển bên trong độ trễ của đám mây của Amazon nên ngắn và vì các tệp đang được truyền trực tiếp nên thời gian thực tế cần phải là thời gian để giải nén luồng.

Có một lý do cố hữu tại sao điều này sẽ không hoạt động hoặc có điều gì đó trong mã của tôi khiến mã này chậm quá không? Đây là lần đầu tiên tôi làm việc với node.js vì vậy tôi có thể làm điều gì đó tồi tệ. Hoặc là có một cách tốt hơn để làm điều này mà tôi không thể tìm thấy với google?

Dưới đây là một phác thảo của mã (BufferStream là một lớp học tôi đã viết rằng kết thúc tốt đẹp Buffer được trả về bởi s3.getObject() thành một readStream)

var aws = require('aws-sdk'); 
var s3 = new aws.S3({apiVersion: '2006-03-01'}); 
var unzip = require('unzip'); 
var stream = require('stream'); 
var util = require("util"); 
var fs = require('fs'); 

exports.handler = function(event, context) { 
    var zipfile = event.Records[0].s3.object.key; 
    s3.getObject({Bucket:SOURCE_BUCKET, Key:zipfile}, 
    function(err, data) { 
     var errors = 0; 
     var total = 0; 
     var successful = 0; 
     var active = 0; 
     if (err) { 
      console.log('error: ' + err); 
     } 
     else { 
      console.log('Received zip file ' + zipfile); 
      new BufferStream(data.Body) 
      .pipe(unzip.Parse()).on('entry', function(entry) { 
       total++; 
       var filename = entry.path; 
       var in_process = ' (' + ++active + ' in process)'; 
       console.log('extracting ' + entry.type + ' ' + filename + in_process); 
       s3.upload({Bucket:DEST_BUCKET, Key: filename, Body: entry}, {}, 
       function(err, data) { 
        var remaining = ' (' + --active + ' remaining)'; 
        if (err) { 
         // if for any reason the file is not read discard it 
         errors++ 
         console.log('Error pushing ' + filename + ' to S3' + remaining + ': ' + err); 
         entry.autodrain(); 
        } 
        else { 
         successful++; 
         console.log('successfully wrote ' + filename + ' to S3' + remaining); 
        } 
       }); 
      }); 
      console.log('Completed, ' + total + ' files processed, ' + successful + ' written to S3, ' + errors + ' failed'); 
      context.done(null, ''); 
     } 
    }); 
} 

Trả lời

3

Tôi nghi ngờ rằng các mô-đun giải nén bạn đang sử dụng là một thực JavaScript cho phép bạn giải nén các tệp zip - rất chậm.

Tôi khuyên bạn nên sử dụng gzip để nén các tệp và sử dụng thư viện nội bộ zlib được biên dịch C và sẽ cung cấp hiệu suất tốt hơn nhiều.

Trong trường hợp bạn chọn gắn bó với zip, bạn có thể liên hệ với bộ phận hỗ trợ amazon và yêu cầu tăng giới hạn 60 giây lên hàm lambda của bạn.

+0

Cảm ơn đề xuất. Tôi đang cố gắng để làm điều này với zlib để so sánh thời gian, nhưng chạy vào một vấn đề với tải lên S3 (http://stackoverflow.com/questions/28688490/untarring-files-to-s3-fails-not-sure-why) – russell

+3

Sau nhiều phép đo hơn, tôi thấy nó là kích thước của các tệp và không phải là số, gây ra sự cố. Nếu tệp lưu trữ chứa tệp văn bản 5MB mà phần lớn thời gian đã mất. Vì vậy, có vẻ như đây không phải là cách đúng để thực hiện việc này. Tôi sẽ viết nó trên EC2 bỏ phiếu từ SQS thay thế. – russell

Các vấn đề liên quan