Solana Geyser gRPC:检测更快,提交没变

Yellowstone gRPC 比 WebSocket 多给了什么、哪些过滤能让它不烧钱,以及为什么世界上最快的数据流也修不好一条慢的发送路径。

BoltTx Team··13 min read
solanageysergrpcyellowstone流式推送交易上链

Geyser 是在 Solana 上"知道某件事发生了"的最快方式。它是验证节点自身的一个插件接口,在更新被处理时就推出来,而不是等它们经过 RPC 层再被服务出去。

团队接上它、测了检测延迟、看到了真实的改善。然后成交率纹丝不动 —— 因为检测本来就不是瓶颈。

Geyser 到底是什么

一个跑在验证节点内部、把更新往外推的插件。Yellowstone 是被广泛使用的 gRPC 实现,所以实践中"Yellowstone gRPC"和"Geyser gRPC"通常指同一件事。

和 WebSocket 订阅的区别:

WebSocket Geyser gRPC
来源 RPC 层 ★验证节点插件★
传输 WS 上的 JSON ★gRPC 上的 protobuf★
过滤 有限 ★丰富、服务端执行★
背压 无 ★gRPC 处理★
费用 通常包含 ★通常付费★

★protobuf 这一点比大多数人以为的更重要。★ 在一个繁忙程序上给每条账户更新解析 JSON 是实打实的 CPU 开销 —— 更新速率一高,它就会取代网络成为你的瓶颈。

怎么订阅

一个 Yellowstone 订阅的形状:

const stream = await client.subscribe();

stream.write({
  accounts: {
    pools: {
      owner: [PROGRAM_ID],            // 该程序拥有的账户
      filters: [{ datasize: "165" }], // ★在服务端过滤★
    },
  },
  transactions: {
    swaps: {
      accountInclude: [PROGRAM_ID],
      failed: false,                  // ★跳过失败的 —— 没什么可反应的★
    },
  },
  commitment: "PROCESSED",            // 最快;动手前先验证
  accountsDataSlice: [],
});

stream.on("data", (update) => {
  if (update.transaction) handleTransaction(update.transaction);
  if (update.account) handleAccount(update.account);
});

★三个设置决定了它好不好用、贵不贵:★

commitment: PROCESSED。 等 CONFIRMED 会花掉一个以上 slot —— 那正是你花钱买速度想避免的东西。接受一小部分可能被回滚,并在动钱之前验证。

服务端过滤。 在繁忙程序上不加过滤的订阅会把一切都推过来。过滤在服务商那一侧执行,所以它同时省下两端的带宽和 CPU。

accountsDataSlice。 如果你只需要一个大账户里的几个字节,就只请求那一段。把完整账户数据推过来然后立刻丢掉,是纯粹的浪费。

如果你的检测已经够快、差距在发送侧,免费领个 BoltTx key 改一行就能拿来对比。

断线重连不是可选项

gRPC 流会断。而且它的失败和 WebSocket 一样安静 —— 你的 handler 只是不再被调用了。

let lastUpdateAt = Date.now();

stream.on("data", (u) => {
  lastUpdateAt = Date.now();
  handle(u);
});

stream.on("error", () => reconnect());
stream.on("end", () => reconnect());

// ★独立的存活检查 —— "安静"和"已死"长得一模一样。★
setInterval(() => {
  if (Date.now() - lastUpdateAt > 60_000) reconnect();
}, 15_000);

★那个定时器和错误处理器同样重要。★ 一条静默卡住的流,既不发 error 也不发 end —— 而一个本来就安静的程序,看起来和死掉的连接一模一样。

它的成本

Geyser 通常是付费产品,而且计费形态和 RPC 不同:

按流或按连接计费,不是按请求。开很多个窄订阅,可能比开一个宽的过滤订阅更贵。

带宽。 在繁忙程序上不加过滤的订阅,是持续不断的大量数据。

你自己的 CPU。 即便是 protobuf,在高更新速率下解析也是实打实的工作。★激进地过滤,而不是解析完再丢掉。★

它帮不上忙的地方

这一节值得在掏钱之前读。

★Geyser 改变的是"你什么时候知道某件事"。它对"你的交易怎么到达出块方"没有任何改变。★

检测     → ★Geyser 在这里起作用★
决策     → 你的代码
提交     → ★Geyser 完全碰不到★
被收录   → 费用、路由、重试

一个检测快到极致、提交却走通用路径的机器人,在拥堵时照样迟到。而拥堵恰恰是你检测到的那些机会出现的时刻。

这笔账值得说直白:★如果你把检测压下去了,而交易仍然要花三个 slot 才落块,那你优化的是总时间里的一小部分,而大头动都没动。★

什么时候 Geyser 值得

值得:

还不值得:

★顺序很重要。★ 先调提交,因为它免费,而且通常是更大的那一项。 然后如果测量结果说你需要,再去买检测速度。

测出哪一半才是你的问题

log({
  eventSlot,                        // 事件发生的 slot
  detectSlot,                       // 你知道它的 slot
  landSlot,                         // 你的反应落块的 slot
  detectLag: detectSlot - eventSlot,   // ★Geyser 改善这个★
  landLag: landSlot - detectSlot,      // ★Geyser 碰不到这个★
});

★如果 landLag 大于 detectLag,那买更快的检测就是在为更小的那一半花钱。★ 这个测量只要一个下午,而它经常会改变团队最后买了什么。

上链应该是什么水平

我们投递节点上的真实交易:中位确认 336 毫秒 —— 不到一个 slot。

★这是 Geyser 碰不到的那一半。★ 不管你多快知道一个事件,你的反应仍然要走完这条路。

BoltTx 在这里的位置

我们是另一半。不做流式推送,不做索引。

你现在的检测方案留着就行 —— 集成点互相独立,换其中一个不用动另一个。提交走我们自建的四区域投递节点,带 SWQoS 路由,不暴露公共 mempool —— 交易在落块之前,传输途中观察不到。

你在本地签名。我们不托管资金、不代签、不修改交易内容。tip 带在交易里、从你自己的钱包链上支付,交易失败时跟着一起 revert —— 这是 Solana 原子交易的机制决定的。只有到达链上的交易才计费。

免费领 API key,没有月费:

// 检测那边不用动,只换发送端点。
const sender = new Connection("https://la.bolttx.io/?api-key=YOUR_KEY");

常见问题

Solana 的 Geyser 是什么? 一个跑在验证节点内部的插件接口,在账户和交易更新被处理时就把它们推出来,而不是等它们经过 RPC 层之后。

Yellowstone gRPC 是什么? Geyser 插件接口被广泛使用的那个 gRPC 实现。实践中"Yellowstone gRPC"和"Geyser gRPC"指的是同一件事。

Geyser 比 WebSocket 订阅快吗? 检测上是的。 它来自验证节点而不是 RPC 层,而且高更新速率下 protobuf 比 JSON 解析更快。但这个优势在"知道事件",不在"发出交易"。

Geyser 能让我的交易更快上链吗? 不能。它改变的是你什么时候知道某个事件。提交走的是另一条路,你的交易多快到达出块方,不受流式配置影响。

Geyser 该用 PROCESSED 还是 CONFIRMED? 时间敏感的场景用 PROCESSED —— 等 CONFIRMED 会花掉一个以上 slot,那正是你花钱要避免的延迟。在动钱之前验证,因为 processed 的结果可能被回滚。

怎么降低 Geyser 的带宽成本? 在服务端过滤,并用 accountsDataSlice 只请求你需要的那几个字节。在繁忙程序上不加过滤,会推过来大量你立刻就丢掉的数据。

怎么检测 Geyser 流卡住了? 不要只依赖 error 和 end 事件 —— 静默卡住的流两个都不发。加一个定时器,当"超过程序合理沉默时长"还没收到更新时就重连。

Geyser 值这个钱吗? 只有当你测出检测是瓶颈时才值。记录"事件到检测"和"检测到落块"两个 slot 距离。如果后者更大,先调提交 —— 那是免费的。

我能自己跑一个 Geyser 插件吗? 能,前提是你跑验证节点。大多数团队不跑 —— 这就是托管 Yellowstone 端点存在的原因。为了拿到 Geyser 而去跑验证节点,单靠这个收益很少划算。

Geyser 和 getProgramAccounts 有什么区别? getProgramAccounts 是请求-响应式的查询,返回当前状态,而且很贵。Geyser 是持续推送发生中的更新。快照 vs 数据流,是两种不同的工具。

Geyser 能取代我的 RPC 吗? 不能。它管流式推送,不管请求和发送。你仍然需要 RPC 来做订阅覆盖不到的读取,以及一条发交易的路径。

用了 Geyser 我的机器人为什么还是输? 因为检测多半本来就不是瓶颈。如果你的交易要花三个以上 slot 才落块,总时间的大头在提交侧 —— 而那是流式推送碰不到的。

一条 gRPC 流上能跑多少个订阅? 一条流上可以配多个过滤器,通常比开几条窄流更便宜。服务商按流或按连接计费,所以把过滤器合并到一条流上往往能降成本。

该把失败的交易从流里过滤掉吗? 大多数交易场景该。失败的交易没有改变状态,所以没什么可反应的,而带上它们只是白白增加流量。

Geyser 保证我不漏任何更新吗? 不保证。流会断,而且重连期间漏掉的东西没有重放缓冲。如果不能接受空缺,重连之后用一次查询把中断那段补回来。

买 Geyser 之前该测什么? "事件到检测"和"检测到落块"这两个 slot 距离,当成两个独立的数字。只有当前者更大时,才该买更快的检测。

延伸阅读

← 返回博客列表