Web3 WebSocket连接阻止节点进程退出

2022-04-01 00:00:00 websocket ethereum web3 solidity javascript

我有一个创建Web3 WebSocket连接的节点js进程,如下所示:

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

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

我在SIGINT和SIGTERM上注册了一个监听器,以观察进程在哪些句柄上有未完成的process._getActiveRequests()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()

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


解决方案

由于EIP-1193和impending release of Web3 1.0.0的实现,Java Web3模块的提供程序API最近发生了一些实质性的变化。

根据the code,看起来web3.currentProvider.disconnect()应该可以工作。此方法还接受可选的codereason参数,如the MDN reference docs for WebSocket.close(...)中所述。

重要提示:您会注意到我引用的是上面的源代码,而不是文档。这是因为目前disconnect方法不被视为公共API的一部分。如果你在你的代码中使用它,你应该确保为它添加一个测试用例,因为它可能在任何时候被破坏!据我所知,WebSocketProvider.disconnect是在web3@1.0.0-beta.38中引入的,并且在今天的最新版本中仍然存在,即web3@1.0.0-beta.55。鉴于稳定的1.0.0版本很快就会下降,我认为从现在到web3@1.0.0不太可能发生太大变化,但在内部API的结构方面没有任何限制。

我已经与GitHub上的当前维护者Samuel Furter(又名Nividia)详细讨论了公开内部提供者。我不完全同意他在这里将其保留在内部的决定,但在他的辩护中,他是目前唯一的维护者,他的双手非常忙于稳定1.0分支机构长期进行的工作。

作为这些讨论的结果,我目前的意见是,那些需要为他们的WebSocket提供程序提供稳定API的人应该编写他们自己的EIP-1193兼容的提供程序,并将其发布在NPM上供其他人使用。请遵循Semver,并在您自己的公共API中包含类似的disconnect方法。如果您在TypeScript中编写它,则会获得额外的加分,因为这使您能够显式地将类成员声明为publicprotectedprivate

如果您这样做,请注意EIP-1193仍处于草稿状态,因此您需要关注EthereumMagicians和Provider Ring Discord上对EIP-1193的讨论,以便随时掌握可能发生的任何更改。

相关文章