2017-05-24 21 views
-1

私は以下の機能を持っています:
1.コレクションfooからmongoDB文書から3000の 'id'プロパティの配列を取得します。
2. IDごとに 'resp' objを取得するために各IDに対してGET要求を作成し、別のデータベースに格納します。エラー:スクレイピング時にETIMEDOUTを接続します

router.get('/', (req, res) => { 

    var collection = db.get().collection('foo'); 
    var collection2 = db.get().collection('test'); 
    collection.distinct('id', (err, idArr) => { // count: 3000+ 
    idArr.forEach(id => { 
    let url = 'https://externalapi.io/id=' + id 
    request(url, (error, response, body) => { 
      if (error) { 
      console.log(error) 
      } else { 
      resp = JSON.parse(resp); 
      collection2.insert(resp); 
      } 
    }); 
}); 

ノード・エラー・ログ:私はレート制限(25cps)が発生しないように、単純なレートリミッタを使用しています

[0] events.js:163 
[0]  throw er; // Unhandled 'error' event 
[0]  ^
[0] 
[0] Error: connect ETIMEDOUT [EXT URL REDACTED] 
[0]  at Object.exports._errnoException (util.js:1050:11) 
[0]  at exports._exceptionWithHostPort (util.js:1073:20) 
[0]  at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1093:14) 

const limit = require("simple-rate-limiter"); 
const request = limit(require("request")).to(20).per(1000); 

しかし、どこかの間に300から1700個の要求をIコマンドラインでノードをクラッシュさせるこのエラーを受け取ります。 このエラーを処理してアプリケーションのクラッシュを防止するにはどうすればよいですか?

あなたが同時にで飛行している要求の最大数を制御したい場合は、私はエラー処理の多くを試してみましたが、それらのどれもがコメントで述べたようにconnect ETIMEDOUT

+1

私は私の前の回答にあなたをリンクされます:あなたはかなり簡単にこのようにそれを行うためにブルーバードを使用することができますhttps://stackoverflow.com/questions/29812692/node-js-server-timeout- problems-ec2-express-pm2/43806215#43806215 – arboreal84

+1

同じホストに同時にいくつのリクエストを実行していますか?私の推測では、あなたのサーバーやデータを取得しようとしているホストのいずれかに問題があります。 – jfriend00

+0

私は2750のIDのために、10個の要求を1秒間実行しようとしています。 私は分裂と征服の方法を統合しているので、ポイントは絞り込むことではありません。私はエラーをキャッチして、プログラムを続行しようとしていますが、 'id'をfailureArrに記録すると、私はarrでスクリプトを実行できます。 @ jfriend00 – Moshe

答えて

2

を処理することができませんでした

const Promise = require('bluebird'); 
const rp = require('request-promise'); 

router.get('/', (req, res) => { 

    let collection = db.get().collection('foo'); 
    let collection2 = db.get().collection('test'); 
    collection.distinct('id', (err, idArr) => { // count: 3000+ 
     if (err) { 
      // handle error here, send some error response 
      res.status(501).send(...); 
     } else { 
      Promise.map(idArr, id => { 
       let url = 'https://externalapi.io/id=' + id 
       return rp(url).then(body => { 
        if (error) { 
         console.log(error) 
        } else { 
         let resp = JSON.parse(body); 
         // probably want to return a promise here too, but I'm unsure what DB you're using 
         collection2.insert(resp); 
        } 
       }).catch(err => { 
        // decide what you want to do when a single request fails here 
        // by providing a catch handler that does not rethrow, other requests will continue 
       }); 
        // pick some concurrency value here that does not cause errors 
      }, {concurrency: 10}).then(() => { 
       // all requests are done, send final response 
       res.send(...); 
      }).catch(err => { 
       // your code may never get here (depends upon earlier .catch() handler) 
      }); 
     } 
    }); 
}); 
+0

とマークします:管理ダッシュボードの管理者が、このボタンが「DBの更新」というボタンをクリックします。クリックすると、このルートがトリガーされます。さて、私は即座に "ok"という応答を送ることができますが、すべての作業はバックグラウンドで行われています...どうすれば確認応答を得ることができますか?すべて完了したらクライアントに応答を送信する(この応答が10分以上かかることを待つ) – Moshe

+0

'//おそらく約束をここにも戻したいと思うが、私はMongoDBを使っていますが、私はここに戻ると約束していますか? – Moshe

+1

@Moshe - ブラウザはHTTPレスポンスのために10分間待つのは本当に好きではありません。それはおそらく両端で様々なトリックで行うことができます。 1つのアイデアは、クライアントにwebSocketまたはsocket.io接続を接続させ、即時のHTTP応答を与え、webSocket/socket.io接続で進行状況を渡すことです。 – jfriend00

関連する問題