Web3 WebSocket连接阻止节点进程退出
我有一个创建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()
应该可以工作。此方法还接受可选的code
和reason
参数,如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
分支机构长期进行的工作。
disconnect
方法。如果您在TypeScript
中编写它,则会获得额外的加分,因为这使您能够显式地将类成员声明为public
、protected
或private
。
如果您这样做,请注意EIP-1193仍处于草稿状态,因此您需要关注EthereumMagicians和Provider Ring Discord上对EIP-1193的讨论,以便随时掌握可能发生的任何更改。
相关文章