Tedious: ConnectionError:连接丢失 - 插入长字符串时写入 ECONNRESET

创建于 2019-07-16  ·  9评论  ·  资料来源: tediousjs/tedious

我在 Azure SQL 数据库上有一个表。

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

我试图在 Signature 列中插入很长的字符串。 如果 packetSize 未设置为 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: truepacketSize: 32768 ,一切正常。

节点版本: v12.6.0

所有9条评论

我们遇到了类似的问题。 尝试插入长字符串时。 经过一番测试,结果表明,在我们的案例中,它与使用的 nodejs 版本有关 dockerized。
节点:10-slim -> 工作正常
节点:12.3.1 -> 工作正常
开始节点:12.4导致套接字挂起或套接字关闭错误。

@ricklang ,我正在寻找这个。 “加密:真”是您这边的必需设置吗? 如果不是,则将其设置为 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: truepacketSize: 32768 ,一切正常。

节点版本: v12.6.0

@wy193777您能否检查是否一切正常而无需其他选项并使用最大 12.3.1 的节点版本?

@susares node v12.3.1 在没有 packetSize 选项的情况下适用于我。

节点版本:v12.2.0 无需 packetSize 选项即可工作
节点版本:v.12.6.0 要求我使用packetSize: 8192来避免Connection lost - read ECONNRESET错误

这似乎是由于https://github.com/nodejs/node/pull/27861。 不知何故,如果写入大的 TLS 段,SQLServer 将终止连接。 我确实有一个修复程序,很快就会打开一个 PR。 👍

对于那些迫不及待的人,这里有一个可以解决这个问题的差异:

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 等级

相关问题

anthonylau picture anthonylau  ·  8评论

arthurschreiber picture arthurschreiber  ·  8评论

ggazulla picture ggazulla  ·  4评论

tvrprasad picture tvrprasad  ·  5评论

ghost picture ghost  ·  5评论