Polkadot RPC 端点实施速率限制以保护基础设施。Substrate 节点内置了如 --rpc-rate-limit 和 --rpc-eth-rate-limit 等标志。公共端点通常设置更严格的限制,返回 429 或断开 WebSocket 连接。本文解释了这些机制,如何通过批处理和退避处理 429 错误,以及如何调整您自己的节点。
直接回答:什么是 Polkadot RPC 速率限制?
Polkadot RPC 速率限制是对您在给定时间窗口内可以发送到 RPC 端点的请求数量的限制。公共端点如 rpc.polkadot.io 通常对每个 IP 强制执行约每秒 5 个请求的限制,而自托管的 Substrate 节点使用 --rpc-rate-limit 标志设置每分钟上限(默认每分钟 100 次调用)。当您超过这些限制时,您会收到 HTTP 429 请求过多响应,或者对于 WebSocket 连接,服务器可能会静默断开连接。
具体限制因提供商而异。例如,OnFinality 的 Polkadot RPC 端点 有文档记录的限制,与社区节点不同。请务必查看您提供商的文档以获取具体数字。
- 公共端点:约 5 请求/秒(文档记录 / 因提供商而异)
- 自托管 Substrate:--rpc-rate-limit 默认 100 次调用/分钟
- 429 是 HTTP 状态;WebSocket 断开是静默的
Substrate RPC 速率限制的工作原理
像 Polkadot 这样的基于 Substrate 的链具有内置的 RPC 速率限制。关键标志是 --rpc-rate-limit(用于一般 RPC 调用)和 --rpc-eth-rate-limit(用于以太坊兼容的 RPC 方法)。这些标志设置每个 IP 每分钟的调用限制。此外,--rpc-max-connections-per-ip 限制每个 IP 的 WebSocket 连接数。
速率限制器使用令牌桶算法。每个 IP 有一个桶,以一定速率填充,并在发出请求时消耗。当桶为空时,请求被拒绝并返回 429 或连接被断开。
公共端点通常设置比 Substrate 默认值更严格的限制,以保护共享基础设施。例如,rpc.polkadot.io 受到严格限制。这在 Polkadot 节点基础设施文档 中有记录。
- --rpc-rate-limit:设置每分钟调用次数(默认 100)
- --rpc-eth-rate-limit:用于 eth_* 方法
- --rpc-max-connections-per-ip:限制 WebSocket 连接数
- 令牌桶算法:随时间补充
429 与超时与 RPC 错误代码
429 请求过多是 HTTP 状态代码,表示您已超过速率限制。它与超时不同,超时意味着服务器在指定时间内未响应。RPC 错误代码(如 -32000)是节点针对无效请求或内部错误返回的 JSON-RPC 错误。
当您收到 429 时,响应可能包含 Retry-After 头,指示重试前需要等待的时间。WebSocket 连接不返回 HTTP 状态代码;相反,服务器可能会关闭连接或发送自定义错误消息。
理解差异有助于您选择正确的处理策略:对于 429,使用退避;对于超时,增加超时时间或减少负载;对于 RPC 错误,修复请求。
- 429:超出速率限制,在 Retry-After 后重试
- 超时:在时间限制内无响应,增加超时或减少负载
- RPC 错误:无效请求,修复请求
识别限制范围
在优化之前,确定限制是按连接还是按 IP,以及它适用于 HTTP 还是 WebSocket。对于 HTTP,限制通常是按 IP 的。对于 WebSocket,可能是按连接或按 IP,具体取决于提供商。
您可以通过从单个连接发送突发请求并观察何时收到 429 或断开连接来测试。还要检查限制是适用于所有方法还是仅适用于特定方法(例如 eth_* 方法)。
使用 RPC 助手 查看各个提供商的文档限制。
- 检查提供商文档以了解按 IP 与按连接的限制
- 通过突发请求测试以查看阈值
- 某些提供商限制特定方法,如 eth_*
减少请求量
避免 429 的最有效方法是减少您发出的请求数量。不要使用 chain_getBlock 轮询新区块,而是使用 chain_subscribeFinalizedHeads 订阅新区块。这会向您推送更新,减少轮询开销。
使用 JSON-RPC 批处理将多个调用合并到一个 HTTP 请求中。这对于只读调用(如 chain_getHeader 或 state_getStorage)特别有效。polkadot.js API 通过 .batch() 方法支持批处理。
缓存不经常更改的存储读取。例如,如果您需要多次读取相同的存储值,请将其存储在本地,并仅在新块到达时刷新。
- 使用订阅而不是轮询
- 将多个调用批处理到一个请求中
- 缓存存储读取并在新区块时失效
使用退避和 Retry-After 处理 429
当您确实收到 429 时,实现带有抖动的指数退避。如果响应包含 Retry-After 头,请等待该秒数后再重试。否则,从短延迟(例如 1 秒)开始,并加倍直到最大值(例如 30 秒)。
对于 WebSocket 连接,如果服务器断开连接,请延迟后重新连接,并考虑降低请求速率。
以下是一个使用 polkadot.js 的 Node.js 示例,演示了批处理和 429 退避:
- 指数退避:1 秒、2 秒、4 秒,... 直到最大值
- 如果存在 Retry-After 头,则遵守它
- 对于 WS,延迟后重新连接
const { ApiPromise, WsProvider } = require('@polkadot/api');
async function main() {
const provider = new WsProvider('wss://rpc.polkadot.io');
const api = await ApiPromise.create({ provider });
// 批处理示例:在一个请求中获取多个头
const batch = api.createType('Vec<BlockNumber>', [100, 200, 300]);
const headers = await api.rpc.chain.getHeader.batch(batch);
console.log('Headers:', headers.map(h => h.number.toString()));
// 429 退避(HTTP 示例)
const fetch = require('node-fetch');
async function rpcCall(method, params) {
let delay = 1000;
while (true) {
const res = await fetch('https://rpc.polkadot.io', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params })
});
if (res.status === 429) {
const retryAfter = res.headers.get('Retry-After');
const wait = retryAfter ? parseInt(retryAfter) * 1000 : delay;
console.log(`429, waiting ${wait}ms`);
await new Promise(r => setTimeout(r, wait));
delay = Math.min(delay * 2, 30000);
} else {
return res.json();
}
}
}
const result = await rpcCall('chain_getHeader', []);
console.log('Header:', result.result.number);
await api.disconnect();
}
main().catch(console.error);
// 预期输出:Headers: ['100', '200', '300'] 和一个头编号常见故障与修复
即使采用最佳实践,您也可能会遇到问题。以下是常见故障及修复方法:
- 静默 WebSocket 断开:服务器关闭连接而不返回 429。修复:实现带有指数退避的重新连接逻辑,并降低请求速率。
- HTTP 上出现 429 但 WS 上没有:某些提供商对 HTTP 和 WS 有不同的限制。修复:使用 WS 进行订阅,使用 HTTP 进行偶尔的读取。
- 特定方法的速率限制:某些提供商对 eth_* 方法的限制更严格。修复:尽可能使用 Substrate 原生方法。
- 批处理未减少 429:如果提供商将每个批处理计为一个请求,则批处理有帮助。如果不是,您可能需要减少总体请求量。
- 静默 WS 断开:实现带退避的重新连接
- HTTP 与 WS 限制:为每种用例使用适当的协议
- 方法特定限制:优先使用原生 Substrate 方法
- 如果提供商单独计算每个调用,批处理可能无济于事
权衡与限制
速率限制对于保护 RPC 基础设施免受滥用是必要的,但它们可能让开发人员感到沮丧。权衡在于可靠性和可访问性之间。公共端点免费但限制严格;专用端点或自托管节点提供更高的限制,但需要付费或维护。
自托管节点让您通过 --rpc-rate-limit 等标志完全控制速率限制。但是,运行节点需要大量资源和维护。对于生产工作负载,请考虑使用像 OnFinality 的 API 服务 这样的提供商,其 RPC 定价 可根据您的需求扩展。
请记住,速率限制不能替代良好的客户端设计。始终最小化请求,使用订阅,并优雅地处理错误。
- 公共端点:免费但有限制
- 自托管:完全控制但维护成本高
- 提供商端点:可扩展但需要付费
- 无论限制如何,良好的客户端设计都是必不可少的
后续步骤与进一步阅读
既然您了解了 Polkadot RPC 速率限制,您可以优化您的应用程序以避免 429。首先确定您的使用模式,并实现批处理和订阅。如果您需要更高的限制,请考虑专用端点或您自己的节点。
如需更多帮助,请查看 OnFinality Learn 中心 获取其他教程,以及 通用 RPC 429 处理 指南。您还可以探索 Polkadot RPC 端点 以比较提供商。
如果您正在 Polkadot 上构建,您可能还对我们的 Polkadot 网络页面 感兴趣,以获取网络详细信息。
- 在您的客户端中实现批处理和订阅
- 考虑为生产环境使用专用端点
- 在 OnFinality Learn 中心 阅读更多内容
- 查看 通用 RPC 429 处理