Tedious: ConnectionError: Соединение потеряно - напишите ECONNRESET при вставке длинной строки

Созданный на 16 июл. 2019  ·  9Комментарии  ·  Источник: tediousjs/tedious

У меня есть таблица в базе данных SQL Azure.

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

Я попытался вставить очень длинную строку в столбец Подпись. Если для packageSize не установлено значение 16384 или выше, я получаю следующее исключение:

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

Ниже моя простая тестовая программа. Я использую последнюю нудную. Кроме того, операция чтения работает нормально для длинной строки независимо от размера пакета. Есть идеи, что я сделал не так?

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

Самый полезный комментарий

Получил Connection lost - read ECONNRESET при выполнении длинного запроса. С encrypt: true и packetSize: 32768 все работает нормально.

версия узла: v12.6.0

Все 9 Комментарий

Мы столкнулись с похожей проблемой. при попытке вставить длинную строку. После небольшого тестирования выясняется, что для нас это связано с используемой версией nodejs в нашем случае dockerized.
узел: 10-тонкий -> отлично работает
узел: 12.3.1 -> отлично работает
начальный узел: 12.4 приводит либо к зависанию сокета, либо к ошибке закрытия сокета.

Привет @ricklang , я искал это. Является ли «шифрование: true» обязательным параметром на вашей стороне? Если это не так, установите для него значение false или просто не устанавливайте его в опции, которая с использованием значения по умолчанию -false также может решить эти проблемы. Я пытался выяснить, почему это происходит, но я не нашел основной причины этого. Я проверил пакеты как для шифрованного, так и для нешифрованного соединения, пакеты абсолютно одинаковые, но для шифрованного при получении последнего пакета с EOM выдается ошибка потери соединения. Я проведу еще немного расследования, посмотрим, смогу ли я что-нибудь откопать.
С другой стороны, мы могли бы также спросить об этом @arthurschreiber , посмотреть, есть ли у него понимание.

С участием

encrypt: false,

Сообщение об ошибке (независимо от размера пакета):

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'

Если удалить параметр шифрования, но оставить размер пакета равным 4096, появится сообщение об ошибке:

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'

Но если увеличить размер пакета до 16384 без набора шифрования, все работает нормально.

Кстати, я тестировал для версий узлов: 12.4.0, 12.6.0. Те же результаты.

Получил Connection lost - read ECONNRESET при выполнении длинного запроса. С encrypt: true и packetSize: 32768 все работает нормально.

версия узла: v12.6.0

@ wy193777 wy193777 , не могли бы вы проверить, все ли работает без дополнительных опций и с максимальной версией узла 12.3.1?

Узел @susares v12.3.1 работает без опции packageSize, которая у меня работает.

версия узла: v12.2.0 работает без параметра packageSize
версия узла: v.12.6.0 требовал, чтобы я использовал packetSize: 8192 , чтобы избежать ошибки Connection lost - read ECONNRESET

Кажется, это связано с https://github.com/nodejs/node/pull/27861. Каким-то образом SQLServer завершит соединение, если будут записаны большие сегменты TLS. У меня есть исправление, и я скоро открою PR. 👍

Для тех, кто не может ждать, вот diff, который это исправит:

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: Эта проблема была решена в версии 6.2.1 :tada:

Релиз доступен на:

Ваш бот семантического выпуска :package::rocket:

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

ggazulla picture ggazulla  ·  4Комментарии

David-Engel picture David-Engel  ·  5Комментарии

tvrprasad picture tvrprasad  ·  6Комментарии

ghost picture ghost  ·  5Комментарии

GuyHarwood picture GuyHarwood  ·  7Комментарии