Tedious: ConnectionError : Connexion perdue - écrire ECONNRESET lors de l'insertion d'une longue chaîne

Créé le 16 juil. 2019  ·  9Commentaires  ·  Source: tediousjs/tedious

J'ai une table sur une base de données Azure SQL.

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

J'ai essayé d'insérer une chaîne très longue dans la colonne Signature. Si le packetSize n'est pas défini sur 16384 ou plus, j'obtiens l'exception suivante :

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

Voici mon programme de test simple. J'utilise la dernière fastidieuse. De plus, l'opération de lecture semble fonctionner correctement pour une longue chaîne, quelle que soit la taille du paquet. Une idée de ce que j'ai fait de 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

Commentaire le plus utile

Vous avez Connection lost - read ECONNRESET lors de l'exécution d'une longue requête. Avec encrypt: true et packetSize: 32768 , tout fonctionne bien.

version du nœud : v12.6.0

Tous les 9 commentaires

Nous rencontrons un problème similaire. lorsque vous essayez d'insérer une longue chaîne. Après quelques tests, il s'avère que pour nous, il est lié à la version nodejs utilisée dans notre cas dockerized.
node:10-slim -> fonctionne bien
node:12.3.1 -> fonctionne bien
nœud de départ : 12.4 entraîne soit un raccrochage de socket, soit une erreur de fermeture de socket.

Salut @ricklang , je cherchais ça. Est-ce que "encrypt: true" est un paramètre obligatoire de votre côté ? Si ce n'est pas le cas, définissez-le sur false ou ne le définissez pas simplement dans l'option qui utilise la valeur par défaut -false peut également résoudre ces problèmes. J'essayais de comprendre pourquoi cela se produisait, mais je n'ai pas trouvé de cause profonde à cela. J'ai vérifié les paquets pour les connexions cryptées et non cryptées, les paquets sont exactement les mêmes, mais pour en crypter un, lorsque le dernier paquet avec EOM est reçu, l'erreur de perte de connexion est reçue. Je vais donner un peu plus d'investigation, voir si je peux déterrer quelque chose.
D'un autre côté, nous pourrions également demander à @arthurschreiber à ce sujet, voir s'il a une idée.

Avec

encrypt: false,

Le message d'erreur est (quelle que soit la taille du paquet) :

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 vous supprimez le paramètre de cryptage, mais laissez la taille de paquet à 4096, le message d'erreur est :

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'

Mais si augmente la taille du paquet à 16384 sans jeu de chiffrement, tout fonctionne bien.

Au fait, j'ai testé les versions de nœud : 12.4.0, 12.6.0. Mêmes résultats.

Vous avez Connection lost - read ECONNRESET lors de l'exécution d'une longue requête. Avec encrypt: true et packetSize: 32768 , tout fonctionne bien.

version du nœud : v12.6.0

@ wy193777 pourriez-vous vérifier si tout fonctionne sans options supplémentaires et en utilisant la version de nœud au maximum 12.3.1 ?

@susares node v12.3.1 fonctionne sans l'option packetSize fonctionne pour moi.

version de nœud : v12.2.0 fonctionne sans l'option packetSize
version de nœud : v.12.6.0 m'a obligé à utiliser packetSize: 8192 pour éviter l'erreur Connection lost - read ECONNRESET

Cela semble être dû à https://github.com/nodejs/node/pull/27861. D'une manière ou d'une autre, SQLServer mettra fin à la connexion si de grands segments TLS sont écrits. J'ai un correctif et j'ouvrirai un PR sous peu. 👍

Pour ceux qui ne peuvent pas attendre, voici le diff qui résoudra cela :

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: Ce problème a été résolu dans la version 6.2.1 :tada:

Le communiqué est disponible sur :

Votre bot sémantique :package::rocket:

Cette page vous a été utile?
0 / 5 - 0 notes