Solana Geyser插件:驱动高速数据流指南

本文介绍了Solana区块链的Geyser gRPC,它提供了一种高性能和灵活的方式,用于直接从Solana区块链流式传输区块、交易、账户和插槽更新。通过Yellowstone Geyser Interface,可以订阅账户、插槽和交易的更新流,适用于构建分析仪表板、实时监控服务或开发工具。Geyser gRPC通过灵活的过滤器、高吞吐量、实时+历史数据结合以及gRPC效率来优化数据流。

Solana 的 Geyser

Geyser gRPC 提供了一种高性能且灵活的方式,可以直接从 Solana 区块链流式传输区块、交易、账户和槽更新。无论你是构建分析仪表板、实时监控服务还是开发工具,本指南都将引导你通过利用 Yellowstone Geyser 接口 订阅各种更新流——账户、槽和交易。

为什么选择 Geyser gRPC?

虽然 Geyser gRPC 专注于通过 gRPC 端点进行流式传输,但 Solana Geyser 插件 是构建在 Solana 验证器本身中的模块化系统。如果出现以下情况,你可以考虑使用 Geyser 插件:

  • 你想要极低级别、近乎即时的数据处理。
  • 你计划将更新直接推送到特定数据库(PostgreSQL、Kafka 等)或消息队列中。
  • 你管理自己的验证器,并且可以在运行时配置动态库(插件)。

Geyser 的超快速流式传输

  • 高吞吐量:Geyser gRPC 适应 Solana 快速的区块生产节奏,支持大量并发订阅。

  • 灵活的过滤器:仅订阅你需要的内容,例如你的链上程序拥有的所有账户,或仅订阅“投票”交易。这可以大大减少应用程序的开销。

  • 实时 + 历史:将实时流式传输(通过 Dragon’s Mouth)与通过 Old Faithful 的历史查询相结合,以完全覆盖链的事件(区块、交易和账户状态)。

  • gRPC 效率:与通过 HTTP/WebSockets 的纯 JSON RPC 相比,gRPC 和协议缓冲区通常提供更低的开销和更高的吞吐量,尤其是在大规模情况下。

Geyser 插件如何工作

  • 验证器加载一个实现“GeyserPlugin” trait 的基于 Rust 的插件。

Geyser 源代码

  • 每次账户、槽或交易更新时,Solana 都会调用相应的函数,如 update_accountnotify_transaction
  • 插件可以随心所欲地处理或存储数据——可能会跳过整个 Solana RPC 开销。

与“AccountsDB 副本”相比,这种插件方法更受欢迎,因为它对于验证器客户端来说更简单,而且更加灵活,可以让你准确地定义应如何流式传输或存储数据。该架构确保你不会用巨大的“getProgramAccounts”查询来拖累验证器。

Geyser gRPC 更新类型概述

  1. 账户更新
  • 当账户的 lamports、数据或所有权发生更改时发出。
  • 对于需要跟踪实时用户余额、流动性池状态或市场数据的 dApp 至关重要。

2. 槽更新

  • 为每个新槽发布,包括父槽和提交级别(已处理、已确认或已最终确定)。
  • 对于区块浏览器、链索引器或任何需要细粒度、逐槽可见性的应用程序很有用。

3. 交易更新

  • 包括交易签名、涉及的账户、状态(例如,成功或失败)和元数据。
  • 它非常适合实时分析、协议指标或合规性日志记录,在这些场景中,你需要账户更改背后的规范“因果关系”。

这些更新类型可以在单个订阅请求中混合和匹配,从而允许你仅获取与你的 dApp 或服务相关的内容。

Rust 客户端入门

yellowstone-grpc repo 中的 Rust 示例演示了如何:

  • 解析命令行参数。
  • 连接到 Geyser gRPC 端点。
  • 设置账户、交易、槽、区块等的订阅过滤器。
  • 通过异步 gRPC 连接处理流式更新。

运行 Geyser GRPC 的简化命令可能如下所示:

cargo run --bin client \
  -- --endpoint <GEYSER_GRPC_ENDPOINT> --x-token <TOKEN> \
  subscribe \
  --accounts \
  --slots \
  --transactions \
  2>&1 | tee output.log

其中:

  • --endpoint 指向 Geyser gRPC URL(例如,https://api.rpcpool.com)。
  • --x-token 是 API Token(如果你的 Geyser 端点需要身份验证)。
  • --accounts--slots--transactions 告诉客户端订阅那些各自的更新。

1. 订阅账户更新

client.rs 中的“Accounts”通过名为 SubscribeRequestFilterAccounts 的过滤器类型进行管理。你可以指定以下条件:

  • Owner Pubkey(即,你的链上程序的地址)。

  • 数据大小(例如,“datasize = 324 bytes”)。

  • Memcmp 条件(offset + base58 数据检查)。

  • 基于 Lamports 的条件(“gt:1000000000”用于过滤高 lamport 账户)。

  • “Accounts token account state”专门用于获取 SPL Token账户;更新包括Token余额和冻结授权更改。

来自 Rust 客户端的代码段可能如下所示:

let filter = SubscribeRequestFilterAccountsFilter {
  filter: Some(AccountsFilterOneof::Memcmp(
    SubscribeRequestFilterAccountsFilterMemcmp {
      offset: 0,
      data: Some(AccountsFilterMemcmpOneof::Base58("Qm...".to_string())),
    },
  )),
};
// ...
let mut accounts = HashMap::new();
accounts.insert(
  "client".to_owned(),
  SubscribeRequestFilterAccounts {
    account: vec!["<SPECIFIC_ACCOUNT_PUBKEY>".to_string()],
    owner: vec!["<YOUR_PROGRAM_PUBKEY>".to_string()],
    filters: vec![filter],
    nonempty_txn_signature: None, // 仅当存在相关交易时才进行流式传输
  },
);

每当这些账户发生更改时(例如,所有权转移、数据写入、lamport 余额修改),相应的更新事件将流式传输到你的客户端。这对于实时监控用户或池状态的 DeFi 协议特别有用。

2. 订阅槽更新

槽实际上是 Solana 区块链的“心跳”:

let mut slots = HashMap::new();
slots.insert(
  "client".to_owned(),
  SubscribeRequestFilterSlots {
    filter_by_commitment: Some(true),
});

通过这样的订阅,你的客户端会收到:

  • 槽的编号及其父槽。
  • 提交级别(它是已处理、已确认还是已最终确定)。
  • 如果槽被标记为“dead”,则会显示错误信息。

基础设施提供商和浏览器通常依赖此信息流来维护最新的链索引,或在槽最终确定后触发后续索引任务。

3. 订阅交易更新

交易给出了链上更改背后的“原因”。通过订阅交易更新,你将看到:

  • 每个新交易的签名。
  • 它是否是投票交易。
  • 参与账户的列表(包括签名者)。
  • 交易成功或失败,以及任何相关的错误消息。

示例过滤器配置:

let mut transactions = HashMap::new();
transactions.insert(
  "client".to_string(),
  SubscribeRequestFilterTransactions {
    // 仅跟踪成功的非投票交易
    vote: Some(false),
    failed: Some(false),
    signature: None,
    account_include: vec!["<ACCOUNT_PUBKEY>".to_string()],
    account_exclude: vec![],
    account_required: vec![],
  },
);

监控交易更新对于需要实时了解用户行为的仪表板或分析特别强大。例如,前端聚合器可能会高亮显示与流行的流动性池交互的每个新交易。

端到端设置的注意事项

  1. 初始状态和快照:在流式传输实时更改之前,收集链当前状态的“快照”,例如使用 Solana 的内置 RPC“getProgramAccounts”或 Project Yellowstone 的 Old Faithful 历史数据。这确保你的本地状态或数据库已正确播种。
  2. 处理错过的更新:如果你的客户端短暂断开连接或重新启动,请考虑使用“from_slot”参数从已知的槽重新订阅,从而降低错过事件的风险。
  3. 性能和过滤:Geyser gRPC 可以传递大量数据。按所有权、lamports 或 memcmp 进行过滤,以减少你这边的带宽和 CPU 使用率。
  4. 提交选择:决定是订阅已处理(最快)、已确认(中等)还是已最终确定(最高确认)状态。正确的选择取决于你需要更新的速度与需要更新的确定性。

整合在一起

这是一个整合的示例,用于订阅账户、槽和交易:

cargo run --bin client -- \
  --endpoint https://api.rpcpool.com/ \
  --x-token <YOUR_TOKEN> \
  subscribe \
  --accounts \
  --accounts-owner <PROGRAM_PUBKEY> \
  --slots \
  --slots-filter-by-commitment \
  --transactions \
  --transactions_account_include <ACCOUNT_PUBKEY> \
  2>&1 | tee subscription.log

说明:

  • Rust 客户端连接到 https://api.rpcpool.com
  • 使用 --x-token 授权自身。
  • 订阅 <PROGRAM_PUBKEY> 拥有的所有账户上的账户更新。
  • 订阅每个新处理的槽。
  • 订阅任何包含 <ACCOUNT_PUBKEY> 的交易。
  • 将输出通过管道传输到“subscription.log”以供以后分析。

最后想法

通过将 Geyser gRPC(用于基于快速订阅的流式传输)与更广泛的 Solana Geyser 插件生态系统相结合,你可以最大限度地减少验证器上的 RPC 开销,并获得现代去中心化应用程序所需的高性能、实时洞察力。

无论你选择哪种方式,请记住:

  • 规划你的数据流。你需要立即的、未经确认的更新,还是只需要最终确定的状态?
  • 确保可靠性。如果你的服务出现故障,请制定从已知槽或参考点重新启动的计划。
  • 尝试使用过滤器。微调的过滤器有助于避免不必要的更新,从而降低带宽成本和客户端开销。

继续学习的资源:

借助 Geyser gRPC,你可以自信地构建下一代 Solana 工具,以满足高吞吐量、实时 DeFi 及其他领域的需求。

  • 原文链接: extremelysunnyyk.medium....
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Yong kang Chia
Yong kang Chia
江湖只有他的大名,没有他的介绍。