最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
yellowstone-grpc:实践指南
时间:2026-09-11 16:28:01 编辑:袖梨 来源:一聚教程网
面对实际交付,我看yellowstone-grpc的重点不在星标,而在这项能力:Triton 的 Dragon's Mouth Yellowstone gRPC 高性能 Solana 流媒体服务。这类日常自动化工具真正难在输入边界、依赖和失败处理如果不清楚就很难稳定复用,仓库说明只能作为第一层证据。与其反复读介绍,不如用一项范围明确的真实任务完成最小试跑,再依据配置时间、输出质量、异常信息和维护痕迹做取舍。我的判断是,它更适合愿意先做小范围验证并复查原始文档的团队;若眼下没有这类需求,先保留观察即可。
Yellowstone Dragon's Mouth - 适用于 Solana 的基于 Geyser 的 gRPC 接口
该存储库包含适用于 Solana 的功能齐全的 gRPC 接口,由 Triton One 构建和维护。它是围绕 Solana 的 Geyser 界面构建的。在此存储库中,我们有多种语言的插件和示例客户端。
它提供了通过标准化路径获取槽、块、交易、预执行交易和账户更新通知的能力。
有关其他文档,请参阅:https://docs.triton.one/rpc-pool/grpc-subscriptions
已知错误
gRPC插件内的块重建基于BlockMeta提供的信息,不幸的是,验证器上生成的块的条目数始终等于零。这些块的条目始终为零。请参阅 GitHub 上的问题:https://github.com/solana-labs/solana/issues/33823
验证器
solana-validator --geyser-plugin-config yellowstone-grpc-geyser/config.json
插件配置检查
cargo-fmt && cargo run --bin config-check -- --config yellowstone-grpc-geyser/config.json
gRPC 、TLS 和身份验证配置
配置 gRPC 侦听器的推荐方法是 grpc.listen。
grpc.listen 是一个数组,其中每个项目可以定义:
address:必填tls:可选,每个侦听器 TLS 配置auth:可选,每者身份验证模式
地址格式
address 接受:
- TCP 套接字为字符串,例如:
"0.0.0.0:10000" - Unix 域套接字作为字符串,例如:
"unix:///var/run/geyser.sock" - 具有显式权限模式的Unix域套接字对象:
{
"address": {
"path": "unix:///var/run/geyser.sock",
"mode": 432
}
}
mode 是十进制(上面的示例是 0o660)。
TLS 选项 ( listen[].tls )
您可以通过两种方式配置TLS:
- 身份对(
cert_path+key_path) - 包含 PEM 文件的证书目录 (
cert_dir)
{
"tls": {
"identity": {
"cert_path": "/etc/yellowstone/tls/server.crt",
"key_path": "/etc/yellowstone/tls/server.key"
}
}
}
{
"tls": {
"cert_dir": "/etc/yellowstone/certs"
}
}
两种形式都接受可选的 watch_file 标志(默认 false)。当 true 时,服务器监视磁盘上的相关路径并热交换所提供的证书,而无需删除现有连接或需要重新启动:
- 身份对:单独监视
cert_path和key_path并在其中任何一个发生更改时重建身份。 - 证书目录:递归监视
cert_dir并在其下的任何文件发生更改时重建 SNI 解析器。
{
"tls": {
"cert_dir": "/etc/yellowstone/certs",
"watch_file": true
}
}
注意事项:
- 对于 Unix 域套接字,TLS 被忽略。
- ALPN 自动配置为 HTTP/2。
身份验证选项 ( listen[].auth )
每个侦听器的身份验证均使用 type 进行配置。
type: "http"
- 使用外部 HTTP 解析器验证请求。
- 解析器预期的请求查询参数:
host和token。 - 解析器成功负载应包括
subscription_id和速率限制(rate_limits或ratelimits)。
HTTP 解析器合约:
- 方法:
GET - URL:
<subscription_resolver_url>?host=<request-host>&token=<x-token> - 所需的查询参数:
host:从传入的gRPC请求URI中提取的主机token:来自传入x-token标头的值
- 预期状态代码:
200 OK:有效的(host, token)对,返回订阅信息JSON404 Not Found:无效的(host, token)对
404 行为很重要:gRPC 服务器将其视为对该 host/token 对的未经身份验证的请求。
请求示例:
GET http://127.0.0.1:8080/?host=api.example.com
示例 200 OK 响应正文:
{
"subscription_id": "test-sub",
"ratelimits": {
"methods": {
"/geyser.Geyser/Subscribe": 2000,
"/geyser.Geyser/SubscribeReplayInfo": 2000,
"/geyser.Geyser/Ping": 2000,
"/geyser.Geyser/GetLatestBlockhash": 2000,
"/geyser.Geyser/GetBlockHeight": 2000,
"/geyser.Geyser/GetSlot": 2000,
"/geyser.Geyser/IsBlockhashValid": 2000,
"/geyser.Geyser/GetVersion": 2000
}
}
}
{
"auth": {
"type": "http",
"subscription_resolver_url": "http://127.0.0.1:8080/",
"subscription_resolution_cache_ttl": "30s",
"max_concurrent_auth_requests": 1000
}
}
type: "file"
- 验证来自本地 JSON 映射文件的请求。
- 该文件应包含包含
token、host和subscription_info的对象数组。
{
"auth": {
"type": "file",
"subscription_resolver_path": "/etc/yellowstone/subscriptions.json"
}
}
示例 /etc/yellowstone/subscriptions.json:
[
{
"token": "test",
"host": "127.0.0.1",
"subscription_info": {
"subscription_id": "test-sub",
"ratelimits": {
"methods": {
"/geyser.Geyser/Subscribe": 2000,
"/geyser.Geyser/SubscribeReplayInfo": 2000,
"/geyser.Geyser/Ping": 2000,
"/geyser.Geyser/GetLatestBlockhash": 2000,
"/geyser.Geyser/GetBlockHeight": 2000,
"/geyser.Geyser/GetSlot": 2000,
"/geyser.Geyser/IsBlockhashValid": 2000,
"/geyser.Geyser/GetVersion": 2000
}
}
}
},
{
"token": "prod-token-1",
"host": "api.example.com",
"subscription_info": {
"subscription_id": "prod-sub-1",
"ratelimits": {
"methods": {
"/geyser.Geyser/Subscribe": 2000,
"/geyser.Geyser/SubscribeReplayInfo": 2000,
"/geyser.Geyser/Ping": 2000,
"/geyser.Geyser/GetLatestBlockhash": 2000,
"/geyser.Geyser/GetBlockHeight": 2000,
"/geyser.Geyser/GetSlot": 2000,
"/geyser.Geyser/IsBlockhashValid": 2000,
"/geyser.Geyser/GetVersion": 2000
}
}
}
}
]
NOTE:方法速率限制尚未实现。
type: "trusted-metadata"
- 信任传入的
x-subscription-id标头并跳过外部身份验证检查。
{
"auth": {
"type": "trusted-metadata"
}
}
计费坚控( listen[].auth.billing )
计费坚控在listen[].auth.billing下配置。
目前支持的模式:
type: "http"
{
"auth": {
"type": "http",
"subscription_resolver_url": "http://127.0.0.1:8080/",
"billing": {
"type": "http",
"billing_endpoint_url": "http://127.0.0.1:8081/billing",
"report_interval": "5s"
}
}
}
注意事项:
- 计费坚控是可选的。
- 如果省略,
report_interval默认为5s。 - 计费事件作为 NDJSON(
application/x-ndjson样式有效负载)发送:每行一个 JSON 事件。 - 事件
code是以下之一:bandwidth:每个请求路径和订阅的计量字节数requests:每个请求路径和订阅的方法调用计数
NDJSON 有效负载示例:
{"code":"bandwidth","subscription_id":"sub-1","method":"/geyser.Geyser/Subscribe","quantity":8192}
{"code":"requests","subscription_id":"sub-1","method":"/geyser.Geyser/Subscribe","quantity":1}
完整的 listen 示例
{
"grpc": {
"listen": [
{
"address": "0.0.0.0:10000",
"auth": {
"type": "http",
"subscription_resolver_url": "http://127.0.0.1:8080/",
"subscription_resolution_cache_ttl": "30s",
"max_concurrent_auth_requests": 1000
}
},
{
"address": "0.0.0.0:10001",
"tls": {
"identity": {
"cert_path": "/etc/yellowstone/tls/server.crt",
"key_path": "/etc/yellowstone/tls/server.key"
},
"watch_file": true
},
"auth": {
"type": "trusted-metadata"
}
},
{
"address": {
"path": "unix:///var/run/geyser.sock",
"mode": 432
},
"auth": {
"type": "file",
"subscription_resolver_path": "/etc/yellowstone/subscriptions.json"
}
}
]
}
}
遗留字段
grpc.address、grpc.tls_config 和 grpc.cert_dir 是旧版本,已弃用,取而代之的是 grpc.listen。
使用 grpc.listen 进行新配置,特别是如果每个端点需要不同的 TLS/auth 行为。
预提交挂钩
安装存储库挂钩:
make install-hooks
预提交挂钩将:
- 确保启用提交签名(
commit.gpgsign=true) - 运行
cargo fmt --all -- --check并在格式化失败时打印警告
块重建
Geyser 区块更新界面不提供有关交易和帐户更新的详细信息。要通过块消息提供此信息,我们必须收集所有消息并期望指定的顺序。默认情况下,如果我们无法重建完整块,我们会记录一条错误消息并增加 prometheus 指标中的 invalid_full_blocks_total 计数器。如果您想对无效重建感到恐慌,请将配置中的选项 block_fail_action 更改为 panic(默认值为 log)。
流数据过滤器
详情请查看yellowstone-grpc-proto/proto/geyser.proto。
commitment— 承诺级别:processed/confirmed/finalizedaccounts_data_slice— 对象数组{ offset: uint64, length: uint64 },允许仅从帐户接收所需的数据ping— 可选布尔字段。如果客户端在一段时间内没有发送任何内容,一些云提供商(例如 Cloudflare、Fly.io)会关闭流。作为解决方法,您可以每 N 秒发送相同的过滤器,但这不是最佳选择,因为您需要保留此过滤器。相反,您可以发送ping字段设置为true的订阅请求,并忽略请求中的其余字段。由于我们每 15 秒从服务器发送一条Ping消息,因此您可以发送带有ping作为回复的订阅请求并接收Pong消息。
filter_by_commitment— 默认情况下,将为所有承诺级别发送插槽,但使用此过滤器,您只能接收选定的承诺级别
账户
帐户可以通过以下方式过滤:
account— 帐户 Pubkey,与数组中的任何 Pubkey 匹配owner— 帐户所有者 Pubkey,与数组中的任何 Pubkey 匹配filters— 与getProgramAccounts过滤器相同,dataSize或Memcmp数组(支持字节、base58、base64)
如果所有字段均为空,则广播所有帐户。否则,字段将用作逻辑 AND,数组中的值将用作逻辑 OR(filters 中的值将用作逻辑 AND)。
交易
vote— enable/disable 广播vote交易failed— enable/disable 广播failed交易signature— 只匹配指定的交易account_include— 过滤使用列表中任何账户的交易account_exclude— 与account_include相反account_required— 要求在交易中使用列表中的所有账户
如果所有字段均为空,则广播所有交易。否则,字段作为逻辑 AND 工作,数组中的值作为逻辑 OR 工作。
粉碎交易
SubscribeDeshred 是用于预执行事务的单独双向流。服务器不是等待 Replay 执行事务并生成 TransactionStatusMeta,而是从传入的碎片中重建条目,并在解码的事务可用时立即对其进行流式传输。
这为您提供了比常规 transactions 流更早的信号,但它附带的上下文较少:
- 可用字段 —
、signature、is_vote、原始transaction、loaded_writable_addresses、loaded_readonly_addresses - 不可用字段 — 执行状态、错误详细信息、日志、内部指令、余额、计算使用情况、
TransactionStatusMeta
loaded_writable_addresses 和 loaded_readonly_addresses 包含从地址查找表解析的地址,因此 deshred 过滤器可以匹配静态帐户密钥和动态加载的地址。
可用性:
- protobuf API 和 Rust 客户端公开
SubscribeDeshred - 此 RPC 仅在 Triton 扩展服务器上可用
- 此存储库中的开源
yellowstone-grpc-geyser服务器当前为SubscribeDeshred返回UNIMPLEMENTED - 实现的版本目前位于
master-triton-ext分支
deshred 事务过滤器支持:
vote— enable/disable 广播vote交易account_include— 匹配提及任何列出帐户的交易,包括 ALT- 加载的地址account_exclude— 排除提及任何列出账户的交易,包括 ALT- 加载的地址account_required— 要求所有列出的帐户都存在,包括 ALT- 加载的地址
参赛作品
目前,我们没有条目过滤器,所有条目都是广播的。
积木
account_include— 过滤使用列表中任何帐户的交易和帐户include_transactions— 包括所有交易include_accounts— 包括所有帐户更新include_entries— 包括所有条目
块元
与 Blocks 相同,但没有 transactions、accounts 和条目。目前,我们没有块元过滤器,所有消息都是广播的。
限制过滤器
可以在配置中添加过滤器限制。如果省略 filters 字段,则过滤器没有任何限制。
"grpc": {
"filters": {
"accounts": {
"max": 1,
"any": false,
"account_max": 10,
"account_reject": ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"],
"owner_max": 10,
"owner_reject": ["11111111111111111111111111111111"]
},
"s": {
"max": 1
},
"transactions": {
"max": 1,
"any": false,
"account_include_max": 10,
"account_include_reject": ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"],
"account_exclude_max": 10,
"account_required_max": 10
},
"blocks": {
"max": 1,
"account_include_max": 10,
"account_include_any": false,
"account_include_reject": ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"],
"include_transactions": true,
"include_accounts" : false,
"include_entries" : false
},
"blocks_meta": {
"max": 1
},
"entry": {
"max": 1
}
}
}
一元 gRPC 方法
平
GetLatestBlockhash
GetBlockHeight
GetSlot
IsBlockhashValid
GetVersion
示例
- 去
- 铁锈
- TypeScript
有关 SubscribeDeshred CLI 示例,请参阅 examples/rust。
[!NOTE] 如果一段时间内客户端没有发送消息,某些负载均衡器将终止 gRPC 连接。 为了缓解这种情况,您需要定期发送消息。 SubscribeRequest 中的
ping字段用于此目的。 gRPC 服务器已经向客户端发送 ping,因此您可以用 ping 进行回复,并且您的连接将保持打开状态。 您可以在 Rust 示例中看到如何使用客户端回复来自服务器的 ping。
基于Geyser gRPC的项目
- https://github.com/rpcpool/yellowstone-grpc-kafka — 将 gRPC 流转发到 Kafka,进行重复数据删除,使用 gRPC 服务器从 Kafka 读取流