359

Node と Cheerio を使用して Web スクレイパーを構築していますが、特定の Web サイトで次のエラーが発生します (これはこの 1 つの Web サイトでのみ発生し、スクレイピングしようとする他の Web サイトでは発生しません。

毎回異なる場所で発生するためurl x、エラーがスローされる場合もあれば、url x問題なく、完全に異なる URL である場合もあります。

    Error!: Error: socket hang up using [insert random URL, it's different every time]

Error: socket hang up
    at createHangUpError (http.js:1445:15)
    at Socket.socketOnEnd [as onend] (http.js:1541:23)
    at Socket.g (events.js:175:14)
    at Socket.EventEmitter.emit (events.js:117:20)
    at _stream_readable.js:910:16
    at process._tickCallback (node.js:415:13)

これはデバッグが非常に難しく、どこから始めればよいかわかりません。まず、ソケット ハングアップ エラーとは何ですか? 404 エラーまたは類似のエラーですか? それとも、サーバーが接続を拒否したということですか?

これの説明がどこにも見つかりません!

編集: (時々) エラーを返すコードのサンプルを次に示します。

function scrapeNexts(url, oncomplete) {
    request(url, function(err, resp, body) {

        if (err) {
            console.log("Uh-oh, ScrapeNexts Error!: " + err + " using " + url);
            errors.nexts.push(url);
        }
        $ = cheerio.load(body);
        // do stuff with the '$' cheerio content here
    });
}

接続を閉じるための直接呼び出しはありませんが、Node Request(私が知る限り) which を使用してhttp.getいるので、これは必須ではありません。間違っている場合は修正してください!

編集 2: これは、エラーを引き起こしている実際の使用中のコードです。prodURLその他の変数は、ほとんどが以前に定義された jquery セレクターです。これはasyncNode.js 用のライブラリを使用します。

function scrapeNexts(url, oncomplete) {
    request(url, function (err, resp, body) {

        if (err) {
            console.log("Uh-oh, ScrapeNexts Error!: " + err + " using " + url);
            errors.nexts.push(url);
        }
        async.series([
                function (callback) {
                    $ = cheerio.load(body);
                    callback();
                },
                function (callback) {
                    $(prodURL).each(function () {
                        var theHref = $(this).attr('href');
                        urls.push(baseURL + theHref);
                    });
                    var next = $(next_select).first().attr('href');
                    oncomplete(next);
                }
            ]);
    });
}
4

30 に答える 30

228

socket hang upgets がスローされるケースは 2 つあります。

あなたがクライアントのとき

クライアントとしてリモート サーバーに要求を送信し、タイムリーな応答を受信しない場合。ソケットが終了すると、このエラーがスローされます。このエラーをキャッチし、それを処理する方法を決定する必要があります。リクエストを再試行するか、後でキューに入れるかなどです。

サーバー/プロキシの場合

サーバーとして、おそらくプロキシ サーバーとして、クライアントからリクエストを受信し、それに基づいて動作を開始 (またはアップストリーム サーバーにリクエストをリレー) し、応答を準備する前に、クライアントはキャンセル/中止を決定します。リクエスト。

このスタック トレースは、クライアントがリクエストをキャンセルしたときに何が起こるかを示しています。

Trace: { [Error: socket hang up] code: 'ECONNRESET' }
    at ClientRequest.proxyError (your_server_code_error_handler.js:137:15)
    at ClientRequest.emit (events.js:117:20)
    at Socket.socketCloseListener (http.js:1526:9)
    at Socket.emit (events.js:95:17)
    at TCP.close (net.js:465:12)

行は@Blenderで言及されているものhttp.js:1526:9を指しています。特に:socketCloseListener

// This socket error fired before we started to
// receive a response. The error needs to
// fire on the request.
req.emit('error', createHangUpError());

...

function createHangUpError() {
  var error = new Error('socket hang up');
  error.code = 'ECONNRESET';
  return error;
}

これは、クライアントがブラウザのユーザーである場合の典型的なケースです。一部のリソース/ページをロードするリクエストには時間がかかり、ユーザーはページを更新するだけです。このようなアクションにより、以前のリクエストが中止され、サーバー側でこのエラーがスローされます。

このエラーはクライアントの希望によるものであるため、クライアントはエラー メッセージを受け取ることを期待していません。したがって、このエラーを重大と見なす必要はありません。無視してください。これは、このようなエラーが発生するresと、クライアントがリッスンしていたソケットが、まだ書き込み可能であるにもかかわらず破棄されるという事実によって助長されます。

console.log(res.socket.destroyed); //true

したがって、応答オブジェクトを明示的に閉じる以外は、何も送信する必要はありません。

res.end();

ただし、すでにリクエストをアップストリームに中継しているプロキシ サーバーである場合に確実に行うべきことは、アップストリームへの内部リクエストを中止することです。これは、応答に関心がないことを示し、アップストリームに伝えます。おそらく、高価な操作を停止します。

于 2015-01-08T07:37:30.423 に答える
60

ソースを見てください:

function socketCloseListener() {
  var socket = this;
  var parser = socket.parser;
  var req = socket._httpMessage;
  debug('HTTP socket close');
  req.emit('close');
  if (req.res && req.res.readable) {
    // Socket closed before we emitted 'end' below.
    req.res.emit('aborted');
    var res = req.res;
    res.on('end', function() {
      res.emit('close');
    });
    res.push(null);
  } else if (!req.res && !req._hadError) {
    // This socket error fired before we started to
    // receive a response. The error needs to
    // fire on the request.
    req.emit('error', createHangUpError());
    req._hadError = true;
  }
}

サーバーが応答を送信しない場合、メッセージが発行されます。

于 2013-06-08T01:51:38.403 に答える
51

言及する価値のある 1 つのケース: Express を使用して Node.js から Node.js に接続するときに、要求された URL パスの前に「/」を付けないと、「ソケット ハングアップ」が発生します。

于 2014-05-13T17:08:34.560 に答える
45

以下は、以下の例でコメント付きのコードを追加しなかったときに同じエラーが発生した簡単な例です。コードのコメントを解除すると、req.end()この問題が解決されます。

var fs = require("fs");
var https = require("https");

var options = {
    host: "en.wikipedia.org",
    path: "/wiki/George_Washington",
    port: 443,
    method: "GET"
};

var req = https.request(options, function (res) {
    console.log(res.statusCode);
});


// req.end();
于 2018-02-09T23:58:57.660 に答える
8

言及する価値のあるもう 1 つのケース (Linux および OS X の場合) はhttps、リクエストを実行するためにライブラリを使用する場合、またはhttps://...ローカルで提供されるインスタンスの URL として渡す場合443、予約済みのプライベート ポートであるポートを使用し、Socket hang upまたはECONNREFUSEDエラーになる可能性があります。

代わりに、 port 3000、 fe を使用して、httpリクエストを実行してください。

于 2016-02-16T13:00:37.227 に答える
6

Nanoライブラリを使用してCouch DBに接続しているときに、同じ問題が発生しました。keepaliveagentライブラリを使用して接続プールを微調整しようとしましたが、ソケット ハングアップメッセージで失敗し続けました。

var KeepAliveAgent = require('agentkeepalive');

var myagent = new KeepAliveAgent({
    maxSockets: 10,
    maxKeepAliveRequests: 0,
    maxKeepAliveTime: 240000
});

nano = new Nano({
    url : uri,
    requestDefaults : {
        agent : myagent
    }
});

苦労した後、私は問題を解決することができました - 結果として、それは非常に単純な間違いでした. HTTPS プロトコル経由でデータベースに接続していましたが、このライブラリの使用例が示すように作成されたキープアライブ エージェントを nano オブジェクトに渡し続けました (http を使用するいくつかのデフォルトに依存しています)。

HttpsAgentを使用する 1 つの簡単な変更でうまくいきました。

var KeepAliveAgent = require('agentkeepalive').HttpsAgent;
于 2015-03-20T09:34:54.583 に答える
0

私の場合、それは application/json 応答の形式が不適切だった (スタック トレースが含まれている) ためでした。応答がサーバーに送信されませんでした。ログがなかったため、デバッグが非常に困難でした。このスレッドは、何が起こるかを理解するのに大いに役立ちます。

于 2017-01-03T07:39:47.377 に答える