---
title: "Geyser gRPC - 最佳實踐"
description: "生產級 Geyser gRPC 客戶端的基本技巧，包括 ping/pong、重連和過濾器。Solana Stream SDK 支援 Geyser gRPC。"
canonical: "https://erpc.global/zh-tw/doc/geyser-grpc/best-practices/"
locale: "zh-tw"
---

# Geyser gRPC - 最佳實踐

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

## 入門

- 從簡單開始：先使用 slot 訂閱熟悉流處理，然後再新增複雜過濾器。  
- 明智使用過濾器：僅訂閱您需要的資料以減少頻寬/CPU 消耗。

```rust
SubscribeRequestFilterTransactions {
    vote: Some(false),   // Exclude 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 通道）。  
- 請先修正無效的請求再重試；只有在回應要求重試時，才使用能辨識暫停指示的指數退避。
- 記錄/統計丟棄的更新以跟蹤消費者過慢的情況。

## 先修正再重試，以及能辨識暫停的退避

在重連迴圈覆蓋之前，先保留第一個 gRPC 錯誤。記錄它的 status 與 message，以及實際存在的 `x-erpc-error-code`、`x-erpc-error-reason`、`x-erpc-doc-url`、`x-erpc-retry-after-seconds` 與 `x-erpc-retry-at` metadata。連線過早關閉時，看起來可能只是一般的傳輸錯誤，因此不一定包含每一個 trailer。

重試前，請先修正無效的請求、被拒絕的過濾器形式，或 IP 註冊不一致的問題。遇到 ERPC 暫停時，請等到回傳的截止時間；它比本機的退避更具體。對可用性失敗與其他可重試的回應，使用有上限的指數退避。不要只因為收到非零 status，就反覆重試未經修改的請求。

## 資源使用與處理能力

Shared 方案的保護機制可防止單一工作負載占用其他 ERPC 客戶所需的傳送容量。串流變慢的原因可能是實際可用頻寬、CPU、記憶體、消費端佇列、資料庫寫入或外部呼叫。資源必須足以應付工作負載；光憑接收端變慢，並無法判斷是哪一部分受到限制。

請在消費端測量資料速率的峰值。以 `MB/s × 8` 將 MB/s 換算成 Mbps，並在測得的峰值之上保留餘裕。沒有不經測量就能套用的固定最低值。讓接收處理保持簡短，將更新交給有界佇列；如果處理跟不上，請擴充處理能力或縮小訂閱範圍。有界佇列能限制記憶體用量，但無法解決持續性的消費端過慢問題。

## 資料管理

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

## 動態訂閱

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

## 生產檢查清單

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

## 其他資源

- Solana Stream SDK（Geyser gRPC 支援）：https://github.com/ValidatorsDAO/solana-stream
