在許多連續和成功的查詢之後,SQL Server 開始拒絕連接
我有一個 GraphQL 伺服器( Node v14.15.1 ),它使用 typeorm 連接到 SQL Server 12.0.4100.1,它也在 docker 容器內執行,連接參數是:
let connection = await createConnection({ type: "mssql", host: HOST, port: PORT, database: DB, username: USER, password: PASSWORD, // NOTE: Use typeorm-model-generator for Entities logging: false, synchronize: true, requestTimeout: 300000, connectionTimeout: 300000, entities: ["./models/mssql"], pool: { max: 1000, min: 1, idleTimeoutMillis: 3000, evictionRunIntervalMillis: 1500000, }, options: { encrypt: false, } })
問題: 在多次成功查詢後,SQL Server 開始拒絕連接並出現以下錯誤:
ConnectionError: Failed to connect to adress: port - connect ECONNREFUSED adress: port\n at ConnectionError (/home/raa/code/wcc-gql/node_modules/mssql/node_modules/tedious/lib/errors.js: 13: 12)\n at Connection.socketError (/home/raa/code/wcc-gql/node_modules/mssql/node_modules/tedious/lib/connection.js: 1290: 56)\n at _connector.Connector.execute (/home/raa/code/wcc-gql/node_modules/mssql/node_modules/tedious/lib/connection.js: 1116: 21)\n at Socket.onError (/home/raa/code/wcc-gql/node_modules/mssql/node_modules/tedious/lib/connector.js: 140: 7)\n at Socket.emit (events.js: 198: 13)\n at emitErrorNT (internal/streams/destroy.js: 91: 8)\n at emitErrorAndCloseNT (internal/streams/destroy.js: 59: 3)\n at process._tickCallback (internal/process/next_tick.js: 63: 19)'
當查詢向下查看層次結構的特定類型有很多解析器時,就會出現問題,而且數據量也會有所不同。數據越多,問題發生的可能性就越大。同樣有趣的是,如果程序在容器內執行或作為 PM2 服務執行,則更有可能出現問題。
我已經測試了相同的數據,其中連接在容器內被拒絕並且在 VS Code 調試器中或從終端執行時沒有被拒絕。我嘗試擺弄池選項,結果適中。我還檢查了我沒有超過數據庫允許的連接數量。我檢查了 SQL Server 上的日誌,在我提出請求時沒有問題或錯誤。我剛剛添加了對在 SQL Server 上跟踪日誌嘗試的支持,它現在在 15:03:46.01 - 15:04:48.07 期間從該應用程序註冊了大約 776 次成功登錄,之後我假設我得到了錯誤。
編輯:
我已經嘗試更改 Sql Server 選項中的 Network Packet Size 選項和 typeorm -> mssql -> tedious 的 packetSize 連接選項,這不起作用,但揭示了一些新的細節。由於我必須重置伺服器應用新的 Sql 選項,因此在重置後查詢成功完成。
因此,我嘗試跟踪資源,發現伺服器很快就達到了 100% 的處理器容量,然後在打開新連接時出現問題,如果我允許池選項中的最大連接數(在我的情況下為 500)太大,它開始拒絕連接。
但是,當我降低 max 屬性時,會出現一種新類型的錯誤,表現為
connection timed out from unknown reason
這次源自tarn.js
.我認為正在發生的事情是 tarm.js(基礎連接池)對於 createTimeoutMillis/ 向池添加新連接有一個預設超時,並且此選項不會通過 typeorm API 顯示,並且它等待伺服器解凍並允許要分配的新連接超時。
你在哪個
node.js
版本?顯然節點版本:v.12.6.0 要求我使用 packetSize: 8192 以避免連接失去 - 讀取 ECONNRESET 錯誤
如果這不是問題,請嘗試更改 SSMS 屬性中的網路數據包大小
如果您說連接大部分都有效但對於不同的數據失敗是因為數據流的大小。
我知道這是一個老問題,我只想分享我解決它的方式,因為這個解決方案對我沒有幫助。我在“池”下發現了一些模糊的超時設置,我增加到了一個荒謬的數量。我不確定其中哪一個有幫助,但這解決了我的問題:
const timeout = 120_000_000; const pool = new sql.ConnectionPool({ user: env.DB_USERNAME, password: env.DB_PASSWORD, server: env.DB_HOST, database: env.DB_DATABASE_NAME, options: { trustServerCertificate: true }, requestTimeout: timeout, pool: { max: 1000, min: 1, idleTimeoutMillis: timeout, acquireTimeoutMillis: timeout, createTimeoutMillis: timeout, destroyTimeoutMillis: timeout, reapIntervalMillis: timeout, createRetryIntervalMillis: timeout, } });