Logo
新用户订阅 RPC,首月享 6.5 折优惠查看优惠
OnFinality Learn
网络与协议指南12分钟阅读

BNB智能链WebSocket RPC:WSS端点、eth_subscribe与重连

了解如何通过WebSocket RPC连接BNB智能链,使用eth_subscribe获取实时数据,并使用ethers.js和web3.js处理重连。

TL;DR

使用BNB智能链WebSocket RPC的全面指南:WSS端点、eth_subscribe方法、连接生命周期以及带代码示例的重连策略。

直接回答:如何通过WebSocket RPC连接BSC

要通过WebSocket RPC连接BNB智能链(BSC),请使用WSS端点,例如主网的wss://bsc-rpc.publicnode.com或测试网的wss://bsc-testnet.publicnode.com。这些端点支持标准的以太坊兼容的eth_subscribe方法,允许您接收新区块、待处理交易和日志的实时通知。对于生产环境应用,您应该使用可靠的提供商,如OnFinality的API服务或专用的RPC提供商,因为公共端点可能存在速率限制和连接不稳定的问题。

本指南解释了BSC WebSocket RPC接口、如何订阅和取消订阅,以及如何构建具有自动重连和重新订阅功能的弹性连接。我们将使用ethers.js和web3.js进行实际示例,并提供常见问题的故障排除清单。

  • 主网WSS:wss://bsc-rpc.publicnode.com(公共网关,由PublicNode提供文档)
  • 测试网WSS:wss://bsc-testnet.publicnode.com(公共网关)
  • 提供商特定端点:因提供商而异(例如QuickNode、Alchemy、OnFinality)——请查看提供商的文档。

BSC WebSocket RPC端点和eth_subscribe方法

BNB智能链与EVM兼容,因此其WebSocket RPC遵循以太坊JSON-RPC规范。实时数据的主要方法是eth_subscribe,它创建订阅并返回订阅ID。支持的订阅类型有:newHeadslogsnewPendingTransactionssyncing

newHeads订阅在每次新区块添加到链上时发送通知。logs订阅根据地址和主题过滤日志,非常适合跟踪合约事件。newPendingTransactions通知您进入内存池的交易哈希,syncing提供同步状态变化。

官方BNB Chain文档(docs.bnbchain.org)确认BSC支持这些标准的以太坊订阅。有关详细的JSON-RPC方法,请参阅BNB Chain JSON-RPC文档

  • newHeads:获取每个新区块头的通知。
  • logs:获取匹配过滤器(地址和主题)的日志。
  • newPendingTransactions:获取待处理交易的哈希。
  • syncing:获取同步状态变化的通知。

使用ethers.js打开WebSocket连接并订阅

要使用ethers.js通过WebSocket连接BSC,您需要使用WSS URL创建一个WebSocketProvider实例。然后您可以使用on方法监听blocklogs等事件。例如,要订阅新区块头,您可以使用provider.on('block', (blockNumber) => { ... })

对于日志,您可以使用provider.on('logs', filter, callback),其中过滤器是一个包含addresstopics的对象。回调接收一个日志对象,其中包含blockNumbertransactionHashdata等字段。

以下是一个最小示例,连接到BSC主网并记录新区块号:

const { WebSocketProvider } = require('ethers');

const wsUrl = 'wss://bsc-rpc.publicnode.com';
const provider = new WebSocketProvider(wsUrl);

provider.on('block', (blockNumber) => {
  console.log('New block:', blockNumber);
});

// Keep the process alive
setTimeout(() => process.exit(0), 30000);

使用web3.js订阅

使用web3.js时,您使用web3.eth.subscribe创建订阅。该方法接受订阅类型和可选参数。例如,要订阅新区块头,您可以这样做:

const Web3 = require('web3');
const web3 = new Web3('wss://bsc-rpc.publicnode.com');

const subscription = web3.eth.subscribe('newBlockHeaders', (error, blockHeader) => {
  if (error) console.error(error);
  console.log('New block header:', blockHeader.number);
});

要取消订阅,请调用subscription.unsubscribe(),它返回一个Promise。对于日志,您可以将过滤器对象作为第二个参数传递:web3.eth.subscribe('logs', { address: '0x...', topics: [...] }, callback)

  • web3.eth.subscribe('newBlockHeaders')用于新区块。
  • web3.eth.subscribe('logs', filter)用于日志。
  • web3.eth.subscribe('newPendingTransactions')用于待处理交易。
  • web3.eth.subscribe('syncing')用于同步状态。

理解通知负载

当您订阅newHeads时,通知负载是一个区块头对象。它包括number(区块号)、hashparentHashtimestamptransactionsRoot等字段。对于logs,负载是一个日志对象,包含addresstopicsdatablockNumbertransactionHashlogIndex

以下是newHeads通知负载的示例:

{
  "jsonrpc": "2.0",
  "method": "eth_subscription",
  "params": {
    "subscription": "0x1234567890abcdef",
    "result": {
      "number": "0x1b4",
      "hash": "0x...",
      "parentHash": "0x...",
      "timestamp": "0x...",
      "transactionsRoot": "0x..."
    }
  }
}

对于日志,负载包括日志的addresstopicsdata和区块信息。您可以使用这些字段触发应用程序逻辑。

  • newHeads负载:区块头,包含numberhashtimestamp等。
  • logs负载:日志对象,包含addresstopicsdatablockNumber等。

连接生命周期:为什么BSC公共WSS端点会断开连接

BSC上的公共WebSocket端点通常由于速率限制、空闲超时或服务器端负载均衡而断开连接。例如,公共网关可能会关闭空闲一段时间或超过请求速率的连接。这是许多公共RPC提供商的文档化行为,但具体限制因提供商而异。

为了保持稳定的连接,您需要实现心跳(keepalive)机制。这可以通过定期发送简单的JSON-RPC请求(如eth_blockNumber)或使用WebSocket协议级别的ping/pong帧来完成。许多库(如ethers.js)具有内置的keepalive选项。

当连接断开时,您必须重新连接并重新订阅您的订阅。这是因为订阅与连接绑定。一个健壮的重连策略包括检测断开、重新连接,然后重新建立所有订阅。您还应该处理重复通知,如果连接在通知发送后但在您收到之前断开,可能会发生重复。

  • 公共端点可能有空闲超时(例如60秒)和速率限制。
  • 使用心跳保持连接活跃。
  • 断开时重新连接并重新订阅。
  • 通过使用幂等处理(例如检查区块号)来处理重复通知。

可运行示例:使用重新订阅重连WebSocketProvider

下面是一个使用ethers.js的完整Node.js脚本,它连接到BSC,订阅新区块和日志,并自动重连并重新订阅。它包括心跳,并通过跟踪最后一个区块号来处理重复通知。

该脚本使用WebSocketProvider并监听close事件以触发重连。它还每15秒发送一个eth_blockNumber请求作为keepalive。重连时,它会重新订阅相同的过滤器。

预期输出:脚本记录新区块号和匹配过滤器的任何日志。断开时,它记录重连消息并恢复。

const { WebSocketProvider } = require('ethers');

const WS_URL = 'wss://bsc-rpc.publicnode.com';
const LOG_FILTER = { address: '0x...' }; // Replace with your contract address

let provider;
let lastBlock = 0;
let reconnectAttempts = 0;

async function connect() {
  console.log('Connecting...');
  provider = new WebSocketProvider(WS_URL);

  provider.on('block', (blockNumber) => {
    if (blockNumber > lastBlock) {
      console.log('New block:', blockNumber);
      lastBlock = blockNumber;
    } else {
      console.log('Duplicate block:', blockNumber);
    }
  });

  provider.on('logs', (log) => {
    console.log('Log:', log.transactionHash, log.blockNumber);
  });

  provider.on('close', () => {
    console.log('Connection closed. Reconnecting...');
    reconnectAttempts++;
    setTimeout(connect, 1000 * Math.min(reconnectAttempts, 5));
  });

  provider.on('error', (error) => {
    console.error('WebSocket error:', error);
  });

  // Heartbeat: send a request every 15 seconds
  setInterval(async () => {
    try {
      await provider.send('eth_blockNumber', []);
    } catch (e) {
      console.error('Heartbeat failed:', e.message);
    }
  }, 15000);
}

connect();

// Keep process alive
setInterval(() => {}, 1000);

故障排除清单:4010、429和连接限制

使用BSC WebSocket RPC时,您可能会遇到特定错误。以下是常见问题及其解决方法:

错误4010(超出订阅限制):当您尝试在单个连接上创建过多订阅时发生。限制通常是每个连接10个订阅,但具体因提供商而异。要解决,请减少订阅数量或使用多个连接。

错误429(请求过多):这是速率限制错误。公共端点通常限制每秒请求数。为避免此问题,请在客户端实现速率限制器或使用具有更高限制的提供商。

每个IP的连接限制:某些提供商限制来自单个IP的并发连接数。如果遇到此问题,您可能需要使用允许更多连接的提供商或将连接分布到多个IP。

区块高度滞后:如果您的订阅未收到最新区块,可能是由于节点落后。使用eth_syncing检查节点的同步状态。如果正在同步,请等待完全同步。

  • 4010:减少订阅或使用多个连接。
  • 429:实现速率限制或升级您的提供商。
  • 连接限制:使用具有更高限制的提供商或分布连接。
  • 区块高度滞后:检查eth_syncing并等待同步。

BSC WebSocket RPC的权衡和限制

WebSocket RPC非常适合实时应用,但也有权衡。它需要持久连接,这可能消耗大量资源。公共端点可能不可靠,因此对于生产环境,请考虑使用专用提供商,如OnFinality的API服务或商业提供商。

此外,newPendingTransactions可能噪音大且量大,请谨慎使用。对于日志,您可以通过指定窄过滤器(地址和主题)来减少量。

最后,请注意BSC的区块时间约为3秒,因此newHeads通知将频繁到达。确保您的客户端能够处理吞吐量。

  • 持久连接需要更多资源。
  • 公共端点可能有速率限制和停机时间。
  • 使用过滤器减少日志量。
  • BSC区块时间约为3秒,因此预计会频繁通知。

后续步骤和进一步阅读

既然您了解了BSC WebSocket RPC,您可以构建实时应用。有关BSC网络特定细节,请参阅BNB智能链网络页面。如果您遇到断开连接问题,请参阅我们的通用WebSocket RPC断开连接修复

有关提供商选择,请查看BNB Chain RPC提供商指南RPC定价。您还可以探索OnFinality Learn中心获取更多教程。

请记住先在测试网上测试您的实现,并始终监控您的连接健康状况。

永远不用担心基础设施

OnFinality 消除了 DevOps 的繁重工作,让您能够更聪明、更快地构建。

开始