2

S3 に保存する画像 URL の配列をアップロードしています。コードは機能しますが、非同期で実行されていません。コンソールへのタイム スタンプは、最初にすべての画像がフェッチされてバッファリングされ、次に s3 に順次保存されることを示しているように見えます。100 個の画像の配列を実行しましたが、最初の画像は 100 番目の画像が取得されるまで s3 に送信されませんでした。少なくとも、画像リクエストのコールバックからコンソールでタイムスタンプのストリームを取得すると、そのように見えます.「s3への保存」タイムスタンプは、最後の画像コールバックのタイムスタンプが付けられるまで開始されません. 私はノードにかなり慣れていません.2日間の実験の後、私はこれを解読していません.

私もそれを直接パイプしようとしましたが、それにはすべてのファイルに content-length を設定する必要があり、そうでないものもあります。最初は getImageFromUrl を 1 つの関数にまとめていましたが、問題がどこにあるのかを突き止めるのに役立つように、それを 3 つの小さな関数に分割しました。s3 には request、knox、async.each イテレータには caolan の async ライブラリを使用しています。コードは次のとおりです。

var images2get = req.body.images2get;  // an array of image urls to be fetched and saved to s3
var startTime = (new Date()).getTime();

//iterate over the array and get each image, save to S3 
var imageNumber = 0;  // this needs to come before the iterator so it's defined

    async.each(images2get, getImageFromUrl, function(err){
        if(err) {
           console.log('async each failed for images2get');
        } else {
           res.send(200);
        }
    });

function getImageFromUrl(url2fetch, nextImage){
    var options = {encoding: null,
                    url: url2fetch, 
                    method: 'GET',
                    timeout: 10*1000
                    }
    request(options, function(err, fetchResponse, body){
        if(!err && fetchResponse && fetchResponse.statusCode == 200) {
            nextImage();  //we've got the image, call the iterator to fetch the next one
            var s3Config = prepareImageForS3(fetchResponse, url2fetch);
            saveToS3(body, s3Config);
        } else {
        //there was a problem fetching the url
        console.log('Error ' + fetchResponse.statusCode + ' Failed to get image from ', url2fetch.absolute);
        nextImage();
        }    
    });
};

function prepareImageForS3(fetchResponse, url2fetch) {
    console.log('preparing image ' + imageNumber + ' at ', (Date.now() - startTime));
    imageNumber += 1;
    var filename = '/' + userId + '/' + pageId + '/image' + imageNumber;
    var headers = {
      'Content-Type': fetchResponse.headers['content-type'],
      'x-amz-acl': 'public-read'
    };
    return{
        'filename': filename,
        'filetype': 'image',
        'filenumber': imageNumber,
        'headers': headers,
        'replaceSrc': true,
        'url': url2fetch
    };
};

function saveToS3(file, s3Config) {
    s3Client.putBuffer(file, s3Config.filename, s3Config.headers, function(err, res){
        console.log('image ' + imageNumber + ' submitting to s3 at ', (Date.now() - startTime));
        //console.log('response from s3 save from url, status:', res.statusCode, 'url:', res.req.url);
        if(!err && res.statusCode === 200 && s3Config.replaceSrc) {
            console.log('image ' + imageNumber + ' saved to s3 at ', (Date.now() - startTime));
        } else {
            console.log('failed to save image to S3 from ' + res.req.url)
        }    
    }); 
};
4

1 に答える 1

0

コードで改善できる点がいくつかあります。

  • HTTP エージェント

まず、node.js は、ホストへの同時接続数を制限するHTTP Agentを使用します。そうでない場合、何千もの接続を持つ Web サイトを誤って簡単に攻撃する可能性があります。

{agent: false}requestに渡すことで無効にできます。knoxではすでに無効になっていることに注意してください。

これが、コードが順番に実行される理由だと思います。

  • Async.each

Async.each は、すべての反復を並行して実行します。を呼び出しているときはnextImage()、async に次の反復を開始するように指示しているのではなく、完了したことを伝えています。すべての反復が完了すると、非同期が完了します。ここでの問題は、async に作業が終了したことを伝えた後も作業を続けていることです。

于 2013-06-13T05:31:00.817 に答える