Geyser gRPC - 最佳實踐

本指南涵蓋構建健壯的生產就緒應用程式時使用 Geyser gRPC 的基本模式。Solana Stream SDK 支援 Geyser gRPC。

入門

  • 從簡單開始:先使用 slot 訂閱熟悉流處理,然後再新增複雜過濾器。
  • 明智使用過濾器:僅訂閱您需要的資料以減少頻寬/CPU 消耗。投票交易約佔流量的 70%——如果不需要就排除它們。
rust
SubscribeRequestFilterTransactions {
    vote: Some(false),   // Exclude ~70% vote txs
    failed: Some(false), // Exclude failed txs
    ..Default::default()
}

連線管理

  • 自動重連:預期會有網路問題;使用指數退避進行重連。
  • Ping/pong 處理:Yellowstone gRPC 伺服器會傳送 ping。務必回覆 pong,否則伺服器可能關閉連線(約 30 秒斷連的常見原因)。
rust
if matches!(update.update_oneof, Some(UpdateOneof::Ping(_))) {
    subscribe_tx.send(SubscribeRequest {
        ping: Some(SubscribeRequestPing { id: 1 }),
        ..Default::default()
    }).await?;
}
  • 間隙恢復:重連後使用 from_slot 避免資料丟失(允許重複)。
rust
subscribe_request.from_slot = if tracked_slot > 0 {
    Some(tracked_slot) // Optionally subtract a small buffer to dodge reorgs
} else {
    None
};

架構模式

  • 使用通道分離接收和處理,以解耦網路 IO 和業務邏輯並新增背壓控制。
rust
let (tx, rx) = mpsc::channel::<SubscribeUpdate>(10_000);
// ingress task reads stream and tx.send(...)
// processing task consumes rx and does business logic
  • 使用有界通道:根據處理速度和資料丟失容忍度選擇容量(較小 = 記憶體少,丟棄多;較大 = 記憶體多,丟棄少)。

效能和彈性

  • 監控處理延遲,超過閾值時記錄日誌。
  • 批次資料庫寫入;按批次大小或時間間隔重新整理。
  • 對外部呼叫使用非同步 IO;將繁重計算解除安裝到工作任務/執行緒。
  • 重用訂閱請求以減少記憶體分配。

錯誤處理

  • 區分錯誤型別(流 vs 處理 vs 通道)。
  • 重連使用指數退避(從小值開始,設定合理上限)。
  • 記錄/統計丟棄的更新以跟蹤消費者過慢的情況。

資料管理

  • 使用 from_slot 時處理重複資料(基於時間的快取或資料庫約束)。
  • 按使用場景選擇確認級別:
    • processed:最快的儀表盤,可能回滾
    • confirmed:大多數應用/索引器的良好預設值
    • finalized:需要絕對確定性時使用

動態訂閱

使用雙向流在執行時更新訂閱(熱切換過濾器、擴大覆蓋範圍),無需重新連線。

生產檢查清單

  • ✅ 帶指數退避的自動重連
  • ✅ 使用 from_slot 的間隙恢復
  • ✅ Ping/pong 處理(避免 30 秒斷連)
  • ✅ 使用有界通道/背壓分離接收和處理
  • ✅ 錯誤日誌和指標/告警
  • ✅ 處理延遲跟蹤
  • ✅ 重複處理和過濾器最佳化
  • ✅ 批次寫入(如有持久化需求)
  • ✅ 優雅關閉和健康檢查

其他資源