NodeJS: ¿Qué significa realmente "el socket cuelga"?

Resuelto JVG asked hace 11 años • 0 respuestas

Estoy creando un raspador web con Node y Cheerio, y para un determinado sitio web aparece el siguiente error (solo ocurre en este sitio web, no en otros que intento raspar).

Sucede en una ubicación diferente cada vez, por lo que a veces es url xlo que arroja el error, otras veces url xestá bien y es una URL completamente diferente:

    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)

Esto es muy complicado de depurar, realmente no sé por dónde empezar. Para empezar, ¿qué ES un error de bloqueo del socket? ¿Es un error 404 o similar? ¿O simplemente significa que el servidor rechazó la conexión?

¡No puedo encontrar una explicación para esto en ninguna parte!

EDITAR: Aquí hay una muestra de código que (a veces) devuelve errores:

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
    });
}

No hay una llamada directa para cerrar la conexión, pero estoy usando Node Requestlos usos (hasta donde yo sé), http.getpor lo que esto no es necesario, ¡corríjame si me equivoco!

EDITAR 2: Aquí hay un fragmento de código real en uso que está causando errores. prodURLy otras variables son en su mayoría selectores de jquery que se definieron anteriormente. Esto utiliza la asyncbiblioteca para Node.

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);
                }
            ]);
    });
}
JVG avatar Jun 08 '13 08:06 JVG
Aceptado

Hay dos casos en los que socket hang upse arroja:

Cuando eres cliente

Cuando usted, como cliente, envía una solicitud a un servidor remoto y no recibe una respuesta oportuna. Su socket finalizó, lo que arroja este error. Debería detectar este error y decidir cómo manejarlo: volver a intentar la solicitud, ponerla en cola para más tarde, etc.

Cuando eres un servidor/proxy

Cuando usted, como servidor, tal vez un servidor proxy, recibe una solicitud de un cliente, luego comienza a actuar en consecuencia (o transmite la solicitud al servidor ascendente) y antes de haber preparado la respuesta, el cliente decide cancelar/abortar. la solicitud.

Este seguimiento de pila muestra lo que sucede cuando un cliente cancela la solicitud.

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)

La línea http.js:1526:9apunta a lo mismo socketCloseListenermencionado por @Blender, en particular:

// 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;
}

Este es un caso típico si el cliente es un usuario del navegador. La solicitud para cargar algún recurso/página lleva mucho tiempo y los usuarios simplemente actualizan la página. Dicha acción hace que se cancele la solicitud anterior, lo que en el lado del servidor arroja este error.

Dado que este error es causado por el deseo de un cliente, no espera recibir ningún mensaje de error. Por lo tanto, no es necesario considerar este error como crítico. Simplemente ignóralo. Esto se ve favorecido por el hecho de que, ante tal error, el ressocket que escuchó su cliente, aunque todavía se puede escribir, se destruye.

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

Entonces, no tiene sentido enviar nada, excepto cerrar explícitamente el objeto de respuesta:

res.end();

Sin embargo, lo que debe hacer con seguridad si es un servidor proxy que ya ha transmitido la solicitud al flujo ascendente es abortar su solicitud interna al flujo ascendente, indicando su falta de interés en la respuesta, lo que a su vez le informará al flujo ascendente. servidor para, tal vez, detener una operación costosa.

esengineer avatar Jan 08 '2015 07:01 esengineer

Eche un vistazo a la fuente :

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;
  }
}

El mensaje se emite cuando el servidor nunca envía una respuesta.

Blender avatar Jun 08 '2013 01:06 Blender

Un caso que vale la pena mencionar: cuando me conecto de Node.js a Node.js usando Express, aparece "el socket cuelga" si no le prefiero "/" a la ruta URL solicitada.

silentorb avatar May 13 '2014 17:05 silentorb