摘要
Polygon 速率限制限制了端点在一个给定时间窗口内接受的 JSON-RPC 请求数量,当您超过限制时,会收到 HTTP 429 响应、WebSocket 订阅被丢弃或静默超时。公共端点在所有调用者之间共享这些限制,因此一个繁重的循环就可能拖垮您的整个应用。
本文解释了 Polygon 速率限制的实际行为、如何解读 429 和重试信号,以及如何根据您的请求量和方法组合在公共端点、托管 RPC API 和专用 Polygon 节点之间进行选择。
Polygon 速率限制实际控制什么
Polygon 速率限制是端点在一个固定时间窗口内为您服务的 JSON-RPC 请求数量的上限。它不是一个单一的数字。提供商通常会同时执行多个限制:每秒请求数、每分钟请求数、并发连接数,有时还会对昂贵的方法(如 eth_getLogs、debug_traceTransaction 或针对归档状态的 eth_call)单独设置上限。
当您超过限制时,端点不会礼貌地排队。它会返回 HTTP 429 Too Many Requests、关闭 WebSocket 或让请求超时。您的客户端会看到调用失败,如果立即重试,只会让问题更糟。
Polygon 主网(链 ID 137)使用 Bor 进行区块生产,使用 Heimdall 进行检查点,公共和托管端点都位于该堆栈之前。速率限制是您调用的端点的属性,而不是 Polygon 网络本身的属性。这一区别很重要:两个端点可以服务同一条链,但在负载下的行为完全不同。
快速建议:哪种端点适合您的流量
在调整重试之前,先确定您现有的端点能否承载您发送的工作负载。以此作为初步判断。
| 您的情况 | 可能的瓶颈 | 合理的下一步 |
|---|---|---|
| 原型设计,每分钟几次调用 | 暂无 | 公共端点可以开始 |
| 具有稳定用户流量的钱包或 dApp | 共享的每 IP 或每密钥上限 | 迁移到使用您自己密钥的托管 RPC API |
| 索引器在长范围内回填日志 | eth_getLogs 上限和超时 | 拆分范围,然后考虑专用节点 |
| 交易机器人或清算人 | 延迟加上每秒上限 | 靠近您应用的专用节点 |
| 对旧区块的归档查询 | 归档可用性,而不仅仅是速率 | 在承诺之前确认归档支持 |
如果您不确定自己属于哪一种,诚实的答案通常是第二行。大多数团队在超出链的能力之前,就已经超出了共享公共端点的能力。
解读信号:429、超时和静默丢弃
速率限制很少会清晰地宣告自己。以下是一些值得识别的模式。
- 带有
Retry-After头的 HTTP 429。 最清晰的信号。遵循该头,而不是以固定间隔重试。 - 没有头的 HTTP 429。 在共享公共端点上很常见。使用指数退避并添加抖动。
eth_getLogs超时。 通常是范围或结果大小限制,而不是每秒上限。- WebSocket 断开连接。 当达到连接限制时,订阅可能会被丢弃;无论提供商如何,您都需要重连逻辑。
- 仅在负载下间歇性失败。 典型的共享上限症状:每秒 10 个请求时正常,每秒 50 个请求时不稳定。
确认原因的一个快速方法是记录每个失败调用的状态码和响应体。许多提供商返回一个 JSON-RPC 错误对象,其消息可以区分限流和错误请求。
# 探测 Polygon 端点并检查状态码和响应体
curl -s -o /tmp/resp.json -w "%{http_code}\n" \
-X POST https://polygon.api.onfinality.io/public \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'
cat /tmp/resp.json
在一个短循环中运行该命令并观察状态码。稳定的 200 流意味着您在限制之内;429 告诉您上限在哪里。
为什么公共 Polygon 端点限流如此激进
公共 RPC 端点的存在是为了让任何人都无需注册即可读取链。这种开放性正是其限制严格的原因。每个调用者共享同一个池,因此提供商必须保护节点免受一个嘈杂客户端饿死其他所有客户端的影响。
在实践中,这意味着公共端点适用于:
- 偶尔读取区块号或 gas 价格
- 在钱包或区块浏览器中进行手动测试
- 当您的主端点宕机时的回退路径
它们不适合:
- 每个区块轮询的循环
- 包含数百次调用的批量请求
- 在宽区块范围内的日志查询
- 任何有面向用户延迟预算的场景
一旦您的应用有真实用户,共享上限就变成了产品风险,而不仅仅是工程细节。这就是团队转向具有专用密钥的托管端点,并在需要可预测吞吐量或归档访问时转向专用节点的时刻。您可以在 RPC 定价 页面上比较这些选项,并查看 支持的 RPC 网络 下有哪些链可用。
最先触及限制的方法
并非所有 JSON-RPC 方法的成本都相同。如果您正在调试速率限制,请检查失败是否集中在少数几个繁重调用上。
| 方法 | 为什么昂贵 | 缓解措施 |
|---|---|---|
eth_getLogs | 扫描许多区块并返回大负载 | 缩小区块范围、分页、缓存结果 |
对旧状态的 eth_call | 需要归档数据 | 除非确实需要历史,否则固定到最近的区块 |
debug_traceTransaction | 重新执行交易 | 谨慎使用,远离热路径 |
包含完整交易的 eth_getBlockByNumber | 每次调用响应大 | 尽可能只请求交易哈希 |
eth_newFilter 轮询 | 随时间推移许多小调用 | 在支持的情况下优先使用 WebSocket 订阅 |
OnFinality 的 Polygon 端点支持 HTTP 和 WebSocket 传输,因此当您想用推送替代轮询时,可以使用基于订阅的模式。有关当前端点和传输详情,请参阅 Polygon 网络页面。
能够承受限流的客户端模式
您无法总是避免速率限制,但可以让客户端在遇到限制时表现良好。
带抖动的退避。 立即重试会将短暂的限流变成持续的限流。带随机抖动的指数退避可以分散重试。
async function rpcWithRetry(url, body, maxRetries = 5) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
if (res.status !== 429) return res.json();
const retryAfter = Number(res.headers.get("retry-after")) || 0;
const base = retryAfter * 1000 || 2 ** attempt * 250;
const wait = base + Math.random() * 250;
await new Promise((r) => setTimeout(r, wait));
}
throw new Error("RPC rate limit: retries exhausted");
}
谨慎批处理。 JSON-RPC 批量请求减少了往返次数,但一批 200 次调用在大多数限制下仍计为 200 次调用。批处理有助于延迟,而不是配额。
缓存不变的内容。 区块号、链 ID 和最终确定的数据可以缓存。不要重新获取已有的区块。
将读路径与写路径分开。 面向用户的读取不应与后台索引器竞争相同的配额。给它们不同的密钥或不同的端点。
添加回退端点。 如果您的主端点返回 429,则故障转移到辅助端点。保持故障转移逻辑简单,并在触发时记录日志,以便了解实际被限流的频率。
何时从共享端点迁移到专用节点
使用您自己密钥的托管 RPC API 提高了您的上限,并让您了解自己的使用情况。专用节点再次改变了等式:您获得为工作负载预留的基础设施,而不是共享池。
在以下情况下考虑专用 Polygon 节点:
- 您的请求速率可预测且足够高,共享上限成为限制因素
- 您需要共享端点限制的归档数据或跟踪方法
- 您希望为延迟敏感的工作负载提供一致的延迟
- 您需要将一个应用的流量与另一个隔离
当您的流量是突发性的、方法组合较轻,并且您宁愿不运营基础设施时,请继续使用托管共享端点。大多数团队首先到达这里,只有在特定方法或流量迫使时才转向专用。OnFinality 提供两种路径,专用节点 页面介绍了预留基础设施涉及的内容。
针对 429 的简短调试清单
当生产环境中出现 Polygon 速率限制错误时,按顺序执行以下步骤:
- 确认状态码和响应体,而不仅仅是客户端错误。
- 确定哪个方法失败,以及它是否是上述繁重调用之一。
- 检查失败是否与部署、cron 作业或流量高峰相关。
- 统计失败窗口期间的实际每秒请求数。
- 验证您是否在没有退避的情况下重试,这会成倍增加负载。
- 检查批处理作业和用户流量是否共享同一个密钥。
- 如果上限确实对您的工作负载来说太低,请评估托管密钥或专用节点。
步骤 1 到 4 通常会揭示原因。步骤 5 和 6 是最常见的自我造成的问题。
关键要点
- Polygon 速率限制由端点执行,而不是链,通常结合每秒、每分钟和并发上限。
- HTTP 429 是最清晰的信号,但
eth_getLogs超时和 WebSocket 断开也是限流症状。 - 公共端点在所有调用者之间共享上限,这使得它们不适合面向用户的流量。
- 带抖动的退避、缓存以及将读路径与批处理作业分开可以减少触及限制的频率。
- 像
eth_getLogs和debug_traceTransaction这样的繁重方法比简单调用更早触及限制。 - 当共享上限成为产品风险时,迁移到托管密钥;当您需要预留吞吐量或归档访问时,迁移到专用节点。
常见问题
公共端点上的 Polygon 速率限制是多少? 它因提供商而异,通常不会以单一数字公布。公共端点通常执行较低的每秒和每 IP 上限,因为容量在所有调用者之间共享。测试您的实际端点,而不是假设一个数字。
为什么我有时会收到 429 错误? 间歇性的 429 通常意味着您接近一个其他调用者也在消耗的共享上限。您的流量在大多数时候没问题,但在高峰期间或批处理作业与用户流量同时运行时就会超限。
批处理 JSON-RPC 请求能避免速率限制吗? 不能。大多数提供商将批处理中的每个调用计入您的配额。批处理减少了网络往返和延迟,而不是请求数量。
如何处理 WebSocket 连接中的 429? 使用退避重新连接并重新订阅您的主题。记录断开连接,以便区分限流和网络问题。订阅限制与 HTTP 请求限制是分开的。
何时应使用专用 Polygon 节点而不是共享端点? 当共享上限是您工作负载的限制因素时,当您需要归档或跟踪方法时,或者当您需要一致的延迟时。如果您的流量轻且突发,托管共享端点通常是更好的选择。
我可以在不运行节点的情况下提高限制吗? 可以。使用您自己密钥的托管 RPC API 为您提供了更高、隔离的上限,而无需运营基础设施。查看 RPC 定价 比较选项,并查看 支持的 RPC 网络 了解可用性。