You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

web3 sendTransaction调用在Ubuntu上CPU负载过高,Windows无此问题

Web3 发送交易Ubuntu环境CPU占满、资源泄漏解决方案

核心问题根因

  1. 未主动销毁Provider底层资源:仅将web3实例赋值为null无法触发底层HTTPProvider的资源回收,绑定的事件监听器会持续持有provider引用,导致GC无法回收socket连接,大量残留连接堆积引发epoll高频轮询占用CPU。
  2. sendTransaction轮询逻辑未终止:你仅在receipt、error回调中修改标志位跳出了业务侧的等待循环,但web3内部监听confirmation的默认逻辑会持续查询区块确认(默认查满24个确认才停止),后台请求没有被主动中断。
  3. 跨平台TCP行为差异:Windows默认的TCP超时回收阈值远短于Ubuntu,你在Windows侧看到的Failed to check for transaction receipt报错就是超时后系统主动断开连接触发了error事件销毁了资源,而Ubuntu侧TCP超时时间长,pm2托管的进程还会忽略部分连接断开信号,导致error事件没有触发,资源泄漏持续累积。
  4. 频繁创建销毁web3实例加剧泄漏:每分钟新建一个web3实例的逻辑本身就会放大资源泄漏的影响。

修复方案

1. 主动销毁Provider连接

不要仅将web3实例设为null,执行完交易逻辑后主动断开底层provider连接,替换原有的web3销毁逻辑:

if (web3T1 != null) {
  // 先断开provider连接,释放socket
  if(web3T1.currentProvider?.disconnect) {
    web3T1.currentProvider.disconnect()
  }
  // 兼容旧版本web3的销毁逻辑
  else if(web3T1.currentProvider?.requestManager?.provider?.destroy) {
    web3T1.currentProvider.requestManager.provider.destroy()
  }
  web3T1 = null
  logger.debug(`provider closed.`)
}

2. 优化sendTransaction监听逻辑,避免后台无效轮询

不要用自定义标志位死等结果,直接用await等待交易执行完成,同时主动限制确认数、及时移除事件监听:

try {
  let confirmedOrReverted = false  
  const receipt = await web3T1.eth.sendTransaction(txData)
    .once('transactionHash', hash => logger.info(`recieved transaction hash: ${hash}`))
    .once('receipt', receipt => {
      logger.info(`Tx receipt => ${receipt.status === true? 'success' : 'failed'}!`)                                                                                 
      confirmedOrReverted = true
    })
    .on('confirmation', (confirmationNumber, receipt) => { 
      logger.info(`recieved confirmation #${confirmationNumber}`); 
      // 达到需要的确认数后主动移除所有监听,终止内部轮询
      if(confirmationNumber >= 1) { // 可根据需要调整确认数阈值
        this.removeAllListeners()
      }
    })
    .once('error', error => { 
      if (error.message.includes('Transaction has been reverted by the EVM')) {
        logger.info(`Transaction has been reverted by the EVM.`) 
      } else {
        logger.error(`TX exception: ${error.message} `)   
      }          
      confirmedOrReverted = true 
    }) 
  // 移除原有while死等逻辑,await会自动等待交易处理完成
} catch(err) {
  logger.error(`error: ${err}`)
}

3. 给HTTP provider加socket强制销毁配置

修改httpOptions,传入自定义HTTP Agent强制超时销毁socket:

const http = require('http')
let httpOptions = {
  keepAlive: false,    
  timeout: 40000, // ms
  agent: new http.Agent({
    keepAlive: false,
    maxSockets: 1,
    timeout: 40000,
    destroyTimeout: 1000 // 超时后1秒强制销毁socket
  })
}

4. 复用全局web3实例

无需每分钟新建web3实例,全局初始化一次即可,避免频繁创建销毁实例带来的额外资源开销。

内容的提问来源于stack exchange,提问作者flo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 10:00:04