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

Polkadot WebSocket RPC:WSS 端点、订阅与重连

了解 Polkadot 的 WebSocket RPC 如何工作,如何使用 @polkadot/api 订阅,以及如何处理断开连接和安全 WSS 端点。

TL;DR

本指南解释 Polkadot 的 WebSocket JSON-RPC 接口,涵盖 wss 与 ws 的区别、默认端口 9944、@polkadot/api 的 WsProvider 如何管理订阅和重连,以及如何使用 nginx 保护 WSS。包含一个可运行的订阅脚本和常见问题(如超时和“fetch failed”)的故障排除清单。

直接回答:关于 Polkadot WebSocket RPC 你需要了解什么

Polkadot 节点暴露一个 WebSocket JSON-RPC 端点(默认端口 9944),允许客户端查询链上数据,并且关键的是,订阅实时更新。安全变体是 wss://(WebSocket Secure),它使用 TLS 加密流量。对于生产环境应用,你应该始终使用 wss:// 端点,例如 OnFinality 的 Polkadot 网络页面 提供的端点。@polkadot/api 库通过其 WsProvider 抽象了 WebSocket 连接,处理订阅和重连逻辑。本指南解释其机制,提供可运行的示例,并为常见连接问题提供故障排除步骤。

如果你正在构建 dApp 或索引器,你可能会使用 @polkadot/api 订阅新区块、最终化头或存储更改。理解 WebSocket 连接在底层如何工作有助于你诊断超时或意外断开等问题。让我们深入架构。

Polkadot WebSocket RPC 如何工作:wss 与 ws 及端口 9944

Polkadot 基于 Substrate,使用 WebSocket 上的 JSON-RPC 进行所有实时交互。默认 WebSocket 端口是 9944,而 HTTP RPC 端口是 9933。ws:// 方案未加密,而 wss:// 使用 TLS 加密。对于任何生产用途,你必须使用 wss:// 以防止窃听和中间人攻击。Polkadot 开发者安全 WebSocket 指南 解释了如何设置安全的 WebSocket 代理。

当你通过 WebSocket 连接到 Polkadot 节点时,客户端发送 JSON-RPC 请求和订阅。订阅是长期存在的请求,服务器推送通知。例如,chain_subscribeNewHeads 在每次导入新区块时发送通知。WebSocket 协议包含 ping/pong 保活机制以检测死连接。如果客户端在特定超时时间内未收到 pong,它可以认为连接已死并尝试重连。

  • 默认 WebSocket 端口:9944
  • 安全 WebSocket:wss://(TLS 加密)
  • 订阅:chain_subscribeNewHeads、chain_subscribeFinalizedHeads、state_subscribeStorage
  • 保活:ping/pong 帧以维持连接

@polkadot/api WsProvider 如何管理连接和订阅

@polkadot/api 库使用 WsProvider 管理 WebSocket 连接。它处理底层 WebSocket 协议,包括重连逻辑和订阅管理。当你使用 WSS 端点创建 API 实例时,WsProvider 建立连接并在连接断开时自动重连。它使用指数退避策略,从短延迟开始,逐渐增加到最大值,以避免压垮服务器。

订阅通过订阅 ID 管理。当你调用 api.rpc.chain.subscribeNewHeads() 时,提供者发送 chain_subscribeNewHeads 请求。服务器响应一个订阅 ID,提供者将该 ID 映射到回调。如果连接断开,提供者重连并自动重新订阅所有活动订阅,使用相同的订阅 ID。这确保你的应用无需手动干预即可继续接收更新。

然而,存在已知问题。例如,一个常见问题是 WsProvider 超时未被 try-catch 捕获,如 Substrate Stack Exchange 所讨论的。这可能导致未处理的 promise 拒绝。此外,'fetch failed' 错误通常发生在 WebSocket 连接未正确建立时,通常是由于网络问题或端点 URL 错误。

可运行示例:使用 @polkadot/api 订阅新区块头

下面是一个完整的、可运行的脚本,它连接到 Polkadot WSS 端点,订阅新区块头,并记录区块号和哈希。它还演示了如何处理断开和重连。要运行它,你需要 Node.js 和 @polkadot/api 包(npm install @polkadot/api)。

该脚本使用 OnFinality 的公共 WSS 端点(如果需要,可以替换为你自己的端点)。它设置订阅并记录每个新区块头。它还监听 'connected' 和 'disconnected' 事件以显示重连行为。

// polkadot-subscribe.js
const { ApiPromise, WsProvider } = require('@polkadot/api');

const WS_URL = 'wss://polkadot.api.onfinality.io/public-ws';

async function main() {
  const provider = new WsProvider(WS_URL);
  const api = await ApiPromise.create({ provider });

  // Log connection events
  provider.on('connected', () => console.log('Connected to', WS_URL));
  provider.on('disconnected', () => console.log('Disconnected from', WS_URL));
  provider.on('error', (err) => console.error('Provider error:', err));

  // Subscribe to new heads
  const unsub = await api.rpc.chain.subscribeNewHeads((head) => {
    console.log(`New block #${head.number} hash: ${head.hash}`);
  });

  // Keep the process alive
  process.on('SIGINT', async () => {
    await unsub();
    await api.disconnect();
    process.exit(0);
  });
}

main().catch(console.error);

预期输出及如何验证

当你运行脚本时,你应该看到类似以下的输出(实际区块号和哈希会有所不同):

Connected to wss://polkadot.api.onfinality.io/public-ws
New block #12345678 hash: 0x1234...abcd
New block #12345679 hash: 0x5678...ef01
...

要验证订阅是否正常工作,你可以将区块号与区块浏览器(如 Polkadot Subscan)上的最新区块进行比较。区块号应每 6 秒增加 1(Polkadot 的平均出块时间)。如果你没有看到新区块,请检查你的网络连接和端点 URL。另外,确保你的防火墙允许端口 443 上的 WebSocket 连接(对于 wss://)。

常见故障及修复:WsProvider 超时和 'fetch failed'

开发者面临的两个常见问题是 WsProvider 超时和 'fetch failed' 错误。超时发生在 WebSocket 连接已建立但服务器在特定时间内未响应时。这可能发生在节点过载或网络缓慢时。WsProvider 对连接建立有一个内置超时(默认 60 秒)。如果超过超时,它会抛出一个错误,该错误可能不会被 ApiPromise.create() 调用周围的 try-catch 捕获,如 Substrate Stack Exchange 所述。要处理此问题,你可以监听提供者的 'error' 事件。

'fetch failed' 错误通常发生在 WebSocket 握手失败时,通常是由于 URL 错误、防火墙阻止连接或 DNS 问题。此错误由 WebSocket 实现使用的底层 fetch API 抛出。要修复它,请验证端点 URL,检查服务器是否可达(例如,使用 curl 或 WebSocket 客户端),并确保你的网络允许出站 WebSocket 连接。

有关 WebSocket RPC 连接为何断开以及如何修复的深入探讨,请参阅我们的指南 为什么 WebSocket RPC 连接会断开

  • 检查端点 URL 和网络连接
  • 监听提供者的 'error' 事件以捕获超时
  • 使用可靠的 WSS 提供商,如 OnFinality 的 RPC Assistant
  • 如果需要,实现自定义重连逻辑

使用 nginx 和 TLS 保护 WSS

如果你运行自己的 Polkadot 节点,你应该通过安全的 WebSocket 端点暴露它。Polkadot 开发者安全 WebSocket 指南 建议使用 nginx 作为反向代理并终止 TLS。这允许你将节点的原生 WebSocket 端口(9944)绑定到 localhost,并在端口 443 上暴露 wss:// 端点。

以下是一个最小的 nginx 配置,它将 WebSocket 连接代理到本地 Polkadot 节点。你需要有 TLS 证书(例如,来自 Let's Encrypt),并配置 proxy_passhttp://127.0.0.1:9944,并带有适当的 WebSocket 头。

server {
    listen 443 ssl;
    server_name rpc.example.com;

    ssl_certificate /etc/letsencrypt/live/rpc.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/rpc.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:9944;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 86400;
    }
}

WebSocket RPC 的权衡与限制

虽然 WebSocket RPC 很强大,但它也有局限性。订阅会消耗节点上的大量资源,尤其是当许多客户端订阅存储更改时。公共端点通常会施加速率限制以保护节点。对于高吞吐量的应用,考虑使用专用端点或像 OnFinality 的 API 服务 这样的服务,它提供可扩展的基础设施。

另一个限制是 WebSocket 连接是有状态的,这在负载均衡环境中可能有问题。如果客户端连接到一台服务器,然后负载均衡器将后续请求路由到另一台,订阅可能会中断。解决方案包括粘性会话或使用集中式 RPC 提供商,后者透明地处理此问题。

最后,重连逻辑可能导致重复通知,如果客户端重连并重新订阅。@polkadot/api 库通过使用订阅 ID 来处理此问题,但你应该注意应用程序逻辑中潜在的重复事件。

后续步骤和更多资源

既然你了解了 Polkadot WebSocket RPC,你可以自信地构建实时应用程序。要开始,请探索 OnFinality 学习中心 获取更多指南,或查看我们的 Polkadot 网络页面 获取可用端点。如果你需要可靠的 RPC 服务,请考虑我们的 定价API 服务

有关 Polkadot RPC 端点的完整列表,请使用我们的 RPC Assistant。如果你遇到连接问题,请参阅我们的指南 为什么 WebSocket RPC 连接会断开。祝你编码愉快!

永远不用担心基础设施

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

开始