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

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

はじめに

  • シンプルに開始: まずは slot 購読でストリームに慣れ、必要に応じてフィルターを追加。
  • フィルターの活用: 必要なデータだけ購読して帯域/CPU を削減。
rust
SubscribeRequestFilterTransactions {
    vote: Some(false),   // vote tx を除外
    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 で並行化し、重い計算はワーカーへ。
  • サブスクリクエストを再利用してアロケーション削減。

エラーハンドリング

  • エラー種別を分離(ストリーム / 処理 / チャンネル)。
  • 誤ったリクエストを修正してから再試行し、再試行できる応答にだけ一時停止を考慮した指数バックオフを使います。
  • スローコンシューマによるドロップをログ/メトリクス化。

再試行前の修正と、一時停止を考慮したバックオフ

再接続で上書きされる前に、最初の gRPC エラーを残します。ステータスとメッセージに加えて、接続開始時と終了時の追加情報にある x-erpc-error-code、x-erpc-error-reason、x-erpc-doc-url、x-erpc-retry-after-seconds、x-erpc-retry-at を記録してください。接続が早期に閉じる場合は一般的な通信エラーに見えることがあり、終了時の追加情報がすべて届くとは限りません。
誤ったリクエスト、拒否された購読条件、IP 登録の不一致は、再試行前に修正します。ERPC が一時停止を返した場合は、ローカルの待機時間より具体的な再試行できる時刻や残り時間を待ってください。一時的に使えない場合など、再試行できる応答には上限付きの指数バックオフを使います。非ゼロのステータスだからといって、同じリクエストを繰り返し再試行しないでください。

リソース使用量と処理能力

Shared の保護は、1 つの利用がほかの ERPC 利用者に必要な配信能力を使い切らないためのものです。ストリームが遅くなる理由には、実効帯域、CPU、メモリ、処理待ちのキュー、データベースへの書き込み、外部サービスの呼び出しがあります。必要なリソースは利用内容に対応していなければならず、受信が遅いことだけでは制約箇所を特定できません。
受信側で最大データレートを計測してください。MB/s × 8 で Mbps に換算し、計測した最大値を超える余裕を確保します。計測なしの固定最低値はありません。受信処理は短くし、更新データは有界キューへ渡します。処理が追いつかない場合は購読を絞るか処理能力を増やしてください。有界キューはメモリ使用量を制限できますが、受信処理が継続的に遅い状態を直すものではありません。

データ管理

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

動的サブスク

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

本番チェックリスト

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

追加リソース