web3 websocket连接阻止节点进程退出

2024-01-01

我有一个创建 web3 websocket 连接的 Node js 进程,如下所示:

web3 = new Web3('ws://localhost:7545')

当进程完成时(我向它发送一个 SIGTERM),它不会退出,而是永远挂起,没有控制台输出。

我在 SIGINT 和 SIGTERM 上注册了一个监听器,以观察进程中哪些句柄未完成process._getActiveRequests() and process._getActiveHandles(),我看到这个:

 Socket {
    connecting: false,
    _hadError: false,
    _handle: 
     TCP {
       reading: true,
       owner: [Circular],
       onread: [Function: onread],
       onconnection: null,
       writeQueueSize: 0 },
    <snip>
    _peername: { address: '127.0.0.1', family: 'IPv4', port: 7545 },
    <snip>
}

为了完整起见,以下是监听信号的代码:

async function stop() {
  console.log('Shutting down...')

  if (process.env.DEBUG) console.log(process._getActiveHandles())

  process.exit(0)
}

process.on('SIGTERM', async () => {
  console.log('Received SIGTERM')
  await stop()
})

process.on('SIGINT', async () => {
  console.log('Received SIGINT')
  await stop()
})

看起来 web3 正在保持套接字打开,这是有道理的,因为我从未告诉它关闭连接。通过查看文档和谷歌搜索,看起来 web3 对象没有 close 或 end 方法。

手动关闭套接字stop上面允许进程成功退出:

web3.currentProvider.connection.close()

有人有更优雅或更官方认可的解决方案吗?我觉得很有趣的是,你必须手动执行此操作,而不是让对象在进程结束时自行销毁。其他客户端似乎会自动执行此操作,而无需明确告诉他们关闭连接。也许告诉节点进程创建的所有客户端在关闭时关闭其句柄/连接会更干净,但对我来说,这是意想不到的。


我觉得很有趣的是,你必须手动执行此操作,而不是让对象在进程结束时自行销毁

这感觉很有趣,因为与异步相比,您可能接触过更多的同步编程。考虑下面的代码

fs = require('fs')
data = fs.readFileSync('file.txt', 'utf-8');
console.log("Read data", data)

当你在上面运行时,你会得到输出

$ node sync.js
Read data Hello World

这是同步代码。现在考虑相同的异步版本

fs = require('fs')
data = fs.readFile('file.txt', 'utf-8', function(err, data) {
    console.log("Got data back from file", data)
});
console.log("Read data", data);

当你运行时你会得到以下输出

$ node async.js
Read data undefined
Got data back from file Hello World

现在如果你认为作为一个同步程序员,程序应该在最后结束console.log("Read data", data);,但你得到的是随后打印的另一条语句。现在这感觉很有趣吗?让我们向进程添加退出语句

fs = require('fs')
data = fs.readFile('file.txt', 'utf-8', function(err, data) {
    console.log("Got data back from file", data)
});
console.log("Read data", data);
process.exit(0)

现在,当您运行该程序时,它会在最后一条语句处结束。

$ node async.js
Read data undefined

但实际上并没有读取该文件。为什么?因为你从来没有给 JavaScript 引擎时间来执行挂起的回调。理想情况下,当没有剩余工作要做(没有待处理的回调、函数调用等...)时,进程会自动完成。这就是异步世界的工作方式。有一些不错的主题和文章值得您研究

https://medium.freecodecamp.org/walking-inside-nodejs-event-loop-85caeca391a9 https://medium.freecodecamp.org/walking-inside-nodejs-event-loop-85caeca391a9

https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/ https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/

Node.js 中如何退出 https://stackoverflow.com/questions/5266152/how-to-exit-in-node-js

为什么在删除所有侦听器后我的 Node.js 进程没有终止? https://stackoverflow.com/questions/26004519/why-doesnt-my-node-js-process-terminate-once-all-listeners-have-been-removed

Node.js 进程如何知道何时停止? https://stackoverflow.com/questions/7698834/how-does-a-node-js-process-know-when-to-stop

因此,在异步世界中,您需要告诉进程退出,或者当没有待处理任务时它会自动退出(您知道如何检查 -process._getActiveRequests() and process._getActiveHandles())

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

web3 websocket连接阻止节点进程退出 的相关文章

随机推荐