dRPC 是一类区块链 RPC 基础设施,它将请求路由到一组分布式的节点运营商,而不是单一的集中式集群。本文解释了该架构背后的思维模型,展示了如何衡量它是否满足你的延迟、一致性和归档数据要求,并提供了一个可复现的诊断流程,你可以对任何端点运行。它将提供商文档中描述的行为与建议以及你必须自行运行的测量区分开来。目标是帮助你基于证据决定,去中心化 RPC 层还是专用节点是你应用的合适基础。
范围与 dRPC 的两种含义
dRPC 一词出现在两个不相关的语境中,将它们混为一谈会导致混淆。第一个是区块链 RPC 基础设施提供商,它将自己宣传为模块化、AI 辅助并分布在众多网络和地区。第二个是 storj/drpc,一个开源、轻量级的 Go 项目 gRPC 直接替代品。本文聚焦于第一种含义:去中心化或分布式的区块链 RPC 基础设施。如果你是为了寻找 Go RPC 框架而来,相关文档在该项目的仓库中,而非此处。
对于区块链团队来说,实际问题不是 dRPC 叫什么,而是分布式 RPC 层能否可靠地服务你的流量。这取决于你的链、方法组合、延迟预算以及你是否需要归档或追踪数据。本指南为你提供一种可重复的方式来回答这个问题,而不是对任何单一提供商下结论。
- 分布式 RPC 基础设施:跨多个节点运营商或集群进行请求路由。
- storj/drpc:一个替代 gRPC 的 Go 库;与区块链端点无关。
- 本文涵盖基础设施含义以及如何评估它。
评估任何端点之前的假设
在比较提供商之前,写下你的工作负载概况。没有它,每个基准测试都是噪音。至少你需要链和网络、你最常调用的 JSON-RPC 方法、峰值每秒请求数、可接受的 p95 和 p99 延迟,以及你是否需要历史状态、日志或追踪。
你还需要一种在改变负载时保持端点不变的方法。使用诸如 RPC_URL 的环境变量,以便同一脚本可以对任何提供商运行。切勿将密钥或端点提交到源代码管理。如果你仍在选择网络,支持的网络目录列出了 OnFinality 所服务的网络,而 RPC 端点指南解释了端点的结构。
- 链、网络和方法组合(例如 eth_call、eth_getLogs、eth_getBlockByNumber)。
- 流量形态:稳态 RPS、突发大小和并发数。
- 数据深度:仅最新状态,还是需要归档和追踪。
- 以 p50、p95 和 p99 目标表示的延迟预算。
分布式 RPC 路由作为思维模型如何运作
集中式 RPC 提供商运行自己的节点和负载均衡器。分布式 RPC 层增加了一个路由层,根据健康状况、延迟或地区在独立节点运营商之间进行选择。路由器是产品;节点由合作伙伴提供。这种设计可以提高抗审查性和地理覆盖范围,但引入了一致性问题:两个连续的请求可能落在具有略微不同链头的不同后端上。
这对读后写模式影响最大。如果你提交交易并立即读取状态,滞后的后端可能返回过时数据。缓解方法是在提供会话亲和性的地方将相关读取固定到一个后端,或者轮询直到区块号前进。理解这种权衡比任何提供商关于节点数量的营销声明更有用。
- 路由层根据健康状况、延迟或地理位置选择后端。
- 独立运营商提高弹性,但可能相差一两个区块。
- 读后写流程需要亲和性或显式的区块高度检查。
使用 curl 的可运行基线检查
从单个请求开始,以确认端点响应并捕获链头。这不是基准测试;这是检查你的凭据和 URL 是否正确的健全性检查。运行三次并注意报告的区块号是否单调递增。
预期的验证结果是一个包含 result 字段(十六进制区块号)的 JSON 对象。如果你收到错误对象,请检查 URL、API 密钥以及该方法是否在该网络上受支持。
export RPC_URL="https://your-endpoint.example/v1/KEY"
curl -s -X POST "$RPC_URL" \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'测量跨后端的延迟和一致性
单个请求无法告诉你分布情况。要检测路由差异,多次发出相同的调用并记录每个请求的区块号和响应时间。下面的脚本发送 50 个请求,打印观察到的不同区块高度,并报告简单的延迟百分位数。对每个候选端点运行它,并将输出记录在结果表中。
不要编造数字。用你自己运行产生的结果填写表格。一个有用的表格每个端点一行,列包括 p50、p95、p99 延迟、观察到的不同区块高度和错误计数。如果分布式端点在短时间内返回多个不同高度,这是预期行为,不一定是故障,但它告诉你应用必须容忍多少陈旧数据。
import os, time, statistics, json, urllib.request
url = os.environ["RPC_URL"]
payload = json.dumps({"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}).encode()
latencies, heights, errors = [], set(), 0
for _ in range(50):
start = time.perf_counter()
req = urllib.request.Request(url, data=payload, headers={"Content-Type":"application/json"})
try:
with urllib.request.urlopen(req, timeout=10) as resp:
body = json.loads(resp.read())
latencies.append((time.perf_counter() - start) * 1000)
heights.add(int(body["result"], 16))
except Exception:
errors += 1
latencies.sort()
def pct(p): return latencies[int(len(latencies) * p) - 1] if latencies else None
print({"p50_ms": pct(0.50), "p95_ms": pct(0.95), "p99_ms": pct(0.99),
"distinct_heights": len(heights), "errors": errors})结果表流程
将你的测量结果记录在如下表格中。在运行脚本之前将单元格留空;结构是交付物,而不是数字。在一天中的三个时间重复运行以捕捉昼夜差异,如果你的应用是突发的,则在并发负载下重复运行。
| 端点标签 | p50 (ms) | p95 (ms) | p99 (ms) | 不同高度数 | 错误数 | 备注 |
|---|---|---|---|---|---|---|
| 候选 A | ||||||
| 候选 B | ||||||
| 专用节点 |
将专用节点行与分布式行进行比较。专用节点应显示单一区块高度和更小的方差;分布式层可能显示更多高度但更好的区域覆盖。两者都不是普遍更好。表格的存在是为了让你的工作负载的权衡变得可见。
测试归档和重型方法
eth_blockNumber 上的延迟不能预测 eth_getLogs 或历史 eth_call 的性能。这些方法开销大,通常是提供商之间真正的区别所在。使用有界区块范围显式测试它们,以免使端点或你自己的脚本过载。
下面的 JavaScript 示例查询小范围内的日志。将地址和主题替换为与你的合约相关的值。如果端点返回关于范围限制的错误,那是你必须围绕设计的文档化约束,而不是暂时性故障。
const RPC_URL = process.env.RPC_URL;
async function getLogs(fromBlock, toBlock) {
const res = await fetch(RPC_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0", id: 1, method: "eth_getLogs",
params: [{ fromBlock, toBlock, address: "0xYourContract" }]
})
});
const body = await res.json();
if (body.error) throw new Error(JSON.stringify(body.error));
return body.result;
}
getLogs("0x100000", "0x100064").then(r => console.log(r.length, "logs"));排查常见故障模式
大多数故障属于几个类别。速率限制返回 HTTP 429 或带有速率消息的 JSON-RPC 错误;使用抖动退避并降低并发。方法不支持错误意味着后端缺乏归档或追踪能力;在假设中断之前,对照提供商的文档确认该方法。陈旧读取表现为区块号落后于链头;在信任状态之前添加高度检查。
如果你仅在负载下看到间歇性 5xx 响应,路由层可能正在卸载流量。捕获响应体和标头,因为提供商通常包含支持人员可以追踪的请求 ID。对于持续性问题,故障排除资源涵盖端点级诊断,而 API 服务概述解释了托管访问的结构。
- 429 或速率错误:降低并发,添加带抖动的指数退避。
- 方法不支持:在重试之前验证归档/追踪支持。
- 区块高度陈旧:轮询直到链头前进或固定到一个后端。
- 负载下间歇性 5xx:记录请求 ID 并联系支持。
局限性以及何时专用节点胜出
分布式 RPC 层以一定的一致性和控制权换取弹性和覆盖范围。如果你的应用需要严格的读后写一致性、非常高的持续吞吐量、自定义插件或大规模下可预测的成本,专用节点通常胜出。专用节点为你提供单一的链头、你自己的资源限制以及调整缓存和索引的能力。
权衡是运维负担:你负责升级、监控和故障转移。对于没有节点运营经验的团队,托管专用产品可以弥合差距。专用节点服务描述了该模式,而 RPC 定价帮助你在承诺之前比较成本结构。
- 选择分布式 RPC 以获得广泛的链覆盖和区域弹性。
- 选择专用节点以获得一致性、吞吐量和自定义控制。
- 无论哪种方式都要为监控和故障转移做预算。
后续步骤以及在哪里获取具体端点
对两到三个候选运行基线和延迟脚本,填写结果表,并与你写下的工作负载概况进行比较。如果数字满足你的 p95 和 p99 目标,并且你的一致性要求得到满足,则进行小比例流量的分阶段推出。
本指南有意不推荐特定链的特定提供商。该选择取决于当前支持、定价和你的地区。对于直接端点或提供商推荐,请使用 RPC Assistant,它维护常见网络问题的简短、最新答案。如果你想了解 OnFinality 如何构建托管访问,请从 API 服务和网络目录开始。