Tedious: ConnectionError: conexión perdida: escriba ECONNRESET al insertar una cadena larga

Creado en 16 jul. 2019  ·  9Comentarios  ·  Fuente: tediousjs/tedious

Tengo una tabla en una base de datos Azure SQL.

CREATE TABLE [dbo].[Owner](
    [OwnerId] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [Name] [varchar](50) NOT NULL,
    [Signature] [varchar](max) NULL
)

Traté de insertar una cadena muy larga en la columna Firma. Si el tamaño del paquete no está configurado en 16384 o superior, obtuve la siguiente excepción:

ConnectionError: Connection lost - write ECONNRESET
    at ConnectionError (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\errors.js:13:12)
    at Connection.socketError (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\connection.js:1187:26)
    at Socket.<anonymous> (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\connection.js:1032:14)
    at Socket.emit (events.js:205:15)
    at errorOrDestroy (internal/streams/destroy.js:107:12)
    at onwriteError (_stream_writable.js:438:5)
    at onwrite (_stream_writable.js:459:5)
    at internal/streams/destroy.js:49:7
    at Socket._destroy (net.js:593:3)
    at Socket.destroy (internal/streams/destroy.js:37:8)
Emitted 'error' event at:
    at Connection.socketError (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\connection.js:1187:12)
    at Socket.<anonymous> (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\connection.js:1032:14)
    [... lines matching original stack trace ...]
    at Socket.destroy (internal/streams/destroy.js:37:8)
    at WriteWrap.onWriteComplete [as oncomplete] (internal/stream_base_commons.js:84:12) {
  message: 'Connection lost - write ECONNRESET',
  code: 'ESOCKET'
}

A continuación se muestra mi programa de prueba simple. Yo uso el último tedioso. Además, la operación de lectura parece funcionar bien para cadenas largas sin importar el tamaño del paquete. ¿Alguna idea de lo que hice mal?

var Connection = require('tedious').Connection;

var config = {
  server: "myserver.database.windows.net",
  options: {
    encrypt: true,
    database: "<mydb>",
    packetSize: 4096,
  },
  authentication: {
    type: "default",
    options: {  
      userName: "<myuser>",
      password: "<mypwd>",
    }
  }
};

var connection = new Connection(config);

connection.on('connect', function(err) {
    // executeStatement();
    executeInsert();
  }
);


var Request = require('tedious').Request;

function executeStatement() {
  /* Read a long string, work fine */
  request = new Request("select OwnerId, Signature From dbo.Owner Where OwnerId = 36", function(err, rowCount) {
    if (err) {
      console.log(err);
    } else {
      console.log(rowCount + ' rows');
    }
  });

  request.on('row', function(columns) {
    columns.forEach(function(column) {
      console.log(column.value);
    });
  });

  connection.execSql(request);
}


function executeInsert() {
  /************************************************
   * Insert a long string, not working when
   *     packetSize = 4096
   * If
   *     packetSize = 16384
   * or higher, insertion works fine.
   *****************************************************/
  let s = '0123456789'.repeat(100000);
  request = new Request("Insert into dbo.Owner VALUES ('Rick', '" + s + "')", function(err, rowCount) {
    if (err) {
      console.log(err);
    } else {
      console.log(rowCount + ' rows');
    }
  });

  connection.execSql(request);
}
released

Comentario más útil

Obtuve Connection lost - read ECONNRESET cuando ejecuté una consulta larga. Con encrypt: true y packetSize: 32768 , todo funciona bien.

versión del nodo: v12.6.0

Todos 9 comentarios

Nos encontramos con un problema similar. al intentar insertar una cadena larga. Después de un poco de prueba, resulta que para nosotros está relacionado con la versión utilizada de nodejs en nuestro caso dockerizado.
nodo: 10-slim -> funciona bien
nodo: 12.3.1 -> funciona bien
nodo inicial: 12.4 da como resultado un bloqueo del socket o un error de cierre del socket.

Hola @ricklang , estaba buscando esto. ¿Es "cifrar: verdadero" una configuración requerida de su lado? Si no es así, configúrelo en falso o simplemente no lo configure en la opción que, al usar el valor predeterminado -falso, también puede resolver estos problemas. Estaba tratando de averiguar por qué sucede esto, pero no he encontrado una causa raíz para esto. Revisé los paquetes para la conexión cifrada y no cifrada, los paquetes son exactamente iguales, pero para cifrar uno, cuando se recibe el último paquete con EOM, se recibe el error de pérdida de conexión. Investigaré un poco más, a ver si puedo desenterrar algo.
Por otro lado, también podríamos preguntarle a @arthurschreiber sobre esto, ver si tiene alguna idea.

Con

encrypt: false,

El mensaje de error es (sin importar el tamaño del paquete):

RequestError: Requests can only be made in the LoggedIn state, not the SentPrelogin state
    at RequestError (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\errors.js:32:12)
    at Connection.makeRequest (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\connection.js:1680:24)
    at Connection.execSql (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\connection.js:1459:10)
    at executeInsert (C:\work\GitRepos\tedious-test\index.js:67:14)
    at Connection.<anonymous> (C:\work\GitRepos\tedious-test\index.js:24:5)
    at Connection.emit (events.js:200:13)
    at Connection.message (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\connection.js:1871:18)
    at Connection.dispatchEvent (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\connection.js:1172:36)
    at MessageIO.<anonymous> (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\connection.js:1045:14)
    at MessageIO.emit (events.js:200:13) {
  message: 'Requests can only be made in the ' +
    'LoggedIn state, not the SentPrelogin ' +
    'state',
  code: 'EINVALIDSTATE'

Si elimina la configuración de cifrado, pero deja el tamaño del paquete en 4096, el mensaje de error es:

ConnectionError: Connection lost - write ECONNRESET
    at ConnectionError (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\errors.js:13:12)
    at Connection.socketError (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\connection.js:1187:26)
    at Socket.<anonymous> (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\connection.js:1032:14)
    at Socket.emit (events.js:205:15)
    at errorOrDestroy (internal/streams/destroy.js:107:12)
    at onwriteError (_stream_writable.js:438:5)
    at onwrite (_stream_writable.js:459:5)
    at internal/streams/destroy.js:49:7
    at Socket._destroy (net.js:593:3)
    at Socket.destroy (internal/streams/destroy.js:37:8)
Emitted 'error' event at:
    at Connection.socketError (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\connection.js:1187:12)
    at Socket.<anonymous> (C:\work\GitRepos\tedious-test\node_modules\tedious\lib\connection.js:1032:14)
    [... lines matching original stack trace ...]
    at Socket.destroy (internal/streams/destroy.js:37:8)
    at WriteWrap.onWriteComplete [as oncomplete] (internal/stream_base_commons.js:84:12) {
  message: 'Connection lost - write ECONNRESET',
  code: 'ESOCKET'

Pero si aumenta el tamaño del paquete a 16384 sin cifrar, todo funciona bien.

Por cierto, probé las versiones de nodo: 12.4.0, 12.6.0. Mismos resultados.

Obtuve Connection lost - read ECONNRESET cuando ejecuté una consulta larga. Con encrypt: true y packetSize: 32768 , todo funciona bien.

versión del nodo: v12.6.0

@ wy193777 ¿podría verificar si todo funciona sin opciones adicionales y usando la versión de nodo al máximo 12.3.1?

@susares node v12.3.1 funciona sin la opción de tamaño de paquete funciona para mí.

versión del nodo: v12.2.0 funciona sin la opción de tamaño de paquete
versión del nodo: v.12.6.0 me obligó a usar packetSize: 8192 para evitar el error Connection lost - read ECONNRESET

Esto parece deberse a https://github.com/nodejs/node/pull/27861. De alguna manera, SQLServer finalizará la conexión si se escriben grandes segmentos TLS. Tengo una solución y abriré un PR en breve. 👍

Para aquellos que no pueden esperar, aquí está la diferencia que solucionará esto:

diff --git a/src/message-io.js b/src/message-io.js
index 90875f8..79f5da8 100644
--- a/src/message-io.js
+++ b/src/message-io.js
@@ -72,6 +72,8 @@ module.exports = class MessageIO extends EventEmitter {
       encrypted: duplexpair.socket2
     };

+    securePair.cleartext.setMaxSendFragment(this.outgoingMessageStream.packetSize);
+
     // If an error happens in the TLS layer, there is nothing we can do about it.
     // Forward the error to the socket so the connection gets properly cleaned up.
     securePair.cleartext.on('error', (err) => {

:tada: Este problema se ha resuelto en la versión 6.2.1 :tada:

El lanzamiento está disponible en:

Su bot de liberación semántica :paquete::cohete:

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

SaloniSonpal picture SaloniSonpal  ·  5Comentarios

aniltomar10 picture aniltomar10  ·  5Comentarios

jstephens7 picture jstephens7  ·  5Comentarios

cdibbs picture cdibbs  ·  6Comentarios

ggazulla picture ggazulla  ·  4Comentarios