Geyser gRPC - ベストプラクティス

Geyser gRPC を堅牢に運用するための基本パターンです。Solana Stream SDK は Geyser gRPC に対応しています。

はじめに

  • シンプルに開始: まずは slot 購読でストリームに慣れ、必要に応じてフィルターを追加。
  • フィルターの活用: 必要なデータだけ購読して帯域/CPU を削減。vote tx は全体の約 70% なので不要なら除外。
rust
SubscribeRequestFilterTransactions { vote: Some(false), // vote tx(約 70%)を除外 failed: Some(false), // 失敗 tx を除外 ..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) // 余裕を見て少し戻すのも可 } else { None };

アーキテクチャ

  • 受信と処理を分離: チャンネルで ingress と処理を分け、バックプレッシャーを持たせる。
rust
let (tx, rx) = mpsc::channel::<SubscribeUpdate>(10_000); // ingress タスク: stream から受信して tx.send(...) // 処理タスク: rx を消費してビジネスロジックを実行
  • 有界チャンネル: 処理速度と許容ドロップ率に応じて容量を選ぶ(小さい=メモリ少・ドロップ多、大きい=メモリ多・ドロップ少)。

パフォーマンスと堅牢性

  • 処理レイテンシ監視(しきい値超過で警告)。
  • DB 書き込みはバッチ化し、サイズまたは時間でフラッシュ。
  • IO は async/await で並行化し、重い計算はワーカーへ。
  • サブスクリクエストを再利用してアロケーション削減。

エラーハンドリング

  • エラー種別を分離(ストリーム / 処理 / チャンネル)。
  • 再接続は指数バックオフ(小さく始めて上限を設定)。
  • スロ―コンシューマによるドロップをログ/メトリクス化。

データ管理

  • from_slot 利用時の重複は時間制限キャッシュや DB 制約で処理。
  • コミットメント選択:
    • processed: 最速ダッシュボード、ロールバックあり
    • confirmed: 多くの本番用途/インデクサーのデフォルト
    • finalized: 確定が必須の金融用途

動的サブスク

双方向ストリームでサブスクをランタイム更新(フィルター差し替え/拡張)できます。

本番チェックリスト

  • ✅ 自動再接続(指数バックオフ)
  • from_slot によるギャップリカバリ
  • ✅ Ping/Pong 対応(30 秒切断を防止)
  • ✅ 受信/処理の分離と有界チャンネル
  • ✅ エラー/メトリクス/アラート
  • ✅ 処理レイテンシ監視
  • ✅ 重複処理とフィルター最適化
  • ✅ バッチ書き込み(永続化する場合)
  • ✅ グレースフルシャットダウンとヘルスチェック

追加リソース