如何使用 Solana Yellowstone gRPC 重新連接和重放插槽

Yellowstone gRPC 是一個功能強大、可用于生產環境且經過實戰檢驗的工具,用于流式傳輸實時的 Solana 數據。但在實際條件下,網絡中斷或服務器重啟可能導致連接中斷。如果沒有適當的重連策略,你的應用程序可能會錯過區塊鏈的關鍵更新。?為了防止這種情況,重要的是構建一個系統,該系統不僅自動重連,而且還從特定的 slot 恢復數據流,從而確保一致性、可靠性和零遺漏事件。

開始之前

要開始,我們需要準備一些東西。

認證:gRPC 端點和 gRPC Token?Shyft 的 gRPC?節點遍布歐盟和美國地區的各個位置。要訪問,我們需要一個特定于區域的 gRPC 端點和一個訪問Token,你可以在?Shyft 儀表板?上購買。

服務器端后端(如 NodeJS)用于接收 gRPC 數據?由于 Web 瀏覽器不支持 gRPC 服務,因此你需要一個后端應用程序,例如 C#、Go、Java、Python?等,來接收 gRPC 數據。

代碼示例:實現重連機制

為了確保流從臨時斷開連接中自動恢復,我們實現了一個簡單的重連循環。如果連接因錯誤而斷開,應用程序會等待一段短暫的延遲,然后使用相同的訂閱請求重新啟動流。這確保了連續的數據流,無需手動干預,即使在不穩定的網絡條件下也是如此。

/*** 重連機制在 handle stream 函數中實現* 如果發生任何錯誤,流將等待 1000 毫秒,然后調用* handleStream 函數,該函數反過來將重新啟動流*/
async function subscribeCommand(client: Client, args: SubscribeRequest) {while (true) {try {await handleStream(client, args); // 訂閱并處理流} catch (error) {console.error("Stream error, retrying in 1 second...", error);await new Promise((resolve) => setTimeout(resolve, 1000));// 可以在這里更改超時時間}}
}

該代碼演示了一個 while 循環,其中調用了?handleStream()?函數。handleStream()?函數負責訂閱和接收流。一旦流中斷,將從 handle stream 函數拋出一個錯誤,該錯誤在循環內處理。然后,循環等待給定的超時時間并迭代,重新發送訂閱請求。

你可以查看?我們的文檔?,或者直接運行 Repl?此處的代碼?以獲取上面示例的完整代碼。

代碼示例:從特定 Slot 重放更新

為了避免在斷開連接期間丟失任何數據,流會跟蹤從每個交易更新收到的最后一個 slot。當流遇到錯誤時,它會嘗試重新連接,并使用?SubscribeRequest?中的 fromSlot 字段從該確切 slot 恢復。此邏輯確保在重新連接時不會跳過任何交易更新。使用重試計數器來防止無限次嘗試 — 達到限制后,系統會回退到從最新的可用 slot 進行流式傳輸。

require("dotenv").config();
import Client, { CommitmentLevel } from "@triton-one/yellowstone-grpc";
import { SubscribeRequest } from "@triton-one/yellowstone-grpc/dist/types/grpc/geyser";
import * as bs58 from "bs58";const MAX_RETRY_WITH_LAST_SLOT = 30;
const RETRY_DELAY_MS = 1000;
const ADDRESS_TO_STREAM_FROM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";type StreamResult = {lastSlot?: string;hasRcvdMSg: boolean;
};async function handleStream(client: Client,args: SubscribeRequest,lastSlot?: string
): Promise<StreamResult> {const stream = await client.subscribe();let hasRcvdMSg = false;return new Promise((resolve, reject) => {stream.on("data", (data) => {const tx = data.transaction?.transaction?.transaction;if (tx?.signatures?.[0]) {const sig = bs58.encode(tx.signatures[0]);console.log("Got tx:", sig);lastSlot = data.transaction.slot;hasRcvdMSg = true;}});stream.on("error", (err) => {stream.end();reject({ error: err, lastSlot, hasRcvdMSg });});const finalize = () => resolve({ lastSlot, hasRcvdMSg });stream.on("end", finalize);stream.on("close", finalize);stream.write(args, (err: any) => {if (err) reject({ error: err, lastSlot, hasRcvdMSg });});});
}async function subscribeCommand(client: Client, args: SubscribeRequest) {let lastSlot: string | undefined;let retryCount = 0;while (true) {try {if (args.fromSlot) {console.log("Starting stream from slot", args.fromSlot);}const result = await handleStream(client, args, lastSlot);lastSlot = result.lastSlot;if (result.hasRcvdMSg) retryCount = 0;} catch (err: any) {console.error(`Stream error, retrying in ${RETRY_DELAY_MS / 1000} second...`);await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY_MS));lastSlot = err.lastSlot;if (err.hasRcvdMSg) retryCount = 0;if (lastSlot && retryCount < MAX_RETRY_WITH_LAST_SLOT) {console.log(`#${retryCount} retrying with last slot ${lastSlot}, remaining retries ${MAX_RETRY_WITH_LAST_SLOT - retryCount}`);args.fromSlot = lastSlot;retryCount++;} else {console.log("Retrying from latest slot (no last slot available)");delete args.fromSlot;retryCount = 0;lastSlot = undefined;}}}
}const client = new Client(process.env.GRPC_URL!, process.env.X_TOKEN!, {"grpc.keepalive_permit_without_calls": 1,"grpc.keepalive_time_ms": 10000,"grpc.keepalive_timeout_ms": 1000,"grpc.default_compression_algorithm": 2,
});const req: SubscribeRequest = {accounts: {},slots: {},transactions: {pumpFun: {vote: false,failed: false,accountInclude: [ADDRESS_TO_STREAM_FROM],accountExclude: [],accountRequired: [],},},transactionsStatus: {},blocks: {},blocksMeta: {},entry: {},accountsDataSlice: [],commitment: CommitmentLevel.CONFIRMED,
};subscribeCommand(client, req);

與上一種方法類似,無限循環確保流在每次斷開連接時都保持重新連接。我們初始化兩個變量,一個用于存儲?lastSlot,即從流收到的最新 slot,另一個用于?retryCount,它限制了從先前 slot 重試的次數,以避免卡在錯誤數據或間隙上。

if (args.fromSlot) {console.log("Starting stream from slot", args.fromSlot);
}

在啟動流之前,代碼檢查是否設置了?fromSlot。如果是,流將從該特定?slot?恢復,而不是從最新的區塊開始。handleStream?函數打開流,偵聽傳入的交易數據,并跟蹤收到的最新 slot。如果收到任何數據,它會將流標記為成功(hasRcvdMSg?=?true)并重置重試計數器,以便系統可以在需要時繼續從上次已知的 slot 重試。

const result = await handleStream(client, args, lastSlot);
lastSlot = result.lastSlot;
if (result.hasRcvdMSg) retryCount = 0;
  • 如果在發生錯誤之前成功記錄了?lastSlot,則將在下一次嘗試中重復使用它。
  • 如果之前的流確實傳遞了數據,我們將重置?retryCount

智能回退

if (lastSlot && retryCount < MAX_RETRY_WITH_LAST_SLOT) {args.fromSlot = lastSlot;retryCount++;
} else {delete args.fromSlot;retryCount = 0;lastSlot = undefined;
}

這是核心的彈性邏輯

  • 如果我們仍然有有效的?lastSlot?并且沒有超過重試限制,我們將嘗試從它恢復。
  • 如果我們重試的次數過多或者沒有有效的 slot,我們將清除?fromSlot?并讓流從區塊鏈的頂端開始。

本文的完整代碼可在?GitHub?上獲取 — 隨意克隆并進行測試。我們還在?GitHub?上分享了一系列涵蓋 gRPC 和 DeFi 的示例用例,你可以克隆并進行實驗。

結論

構建具有?基于 slot 的重放?的重連策略,可確保你的 Solana 應用程序?保持可靠和實時?— 即使在網絡中斷的情況下也是如此。通過跟蹤上次收到的 slot 并智能地重試,你可以從中斷的地方恢復流式傳輸,避免錯過更新或重復數據。這種方法?增加了彈性,并保證了?任何生產級區塊鏈應用程序的?更順暢的?用戶體驗,更多相關文章,請,https://t.me/gtokentool。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/83344.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/83344.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/83344.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

foxmail - foxmail 啟用超大附件提示密碼與帳號不匹配

foxmail 啟用超大附件提示密碼與帳號不匹配 問題描述 在 foxmail 客戶端中&#xff0c;啟用超大附件功能&#xff0c;輸入了正確的賬號&#xff08;郵箱&#xff09;與密碼&#xff0c;但是提示密碼與帳號不匹配 處理策略 找到 foxmail 客戶端目錄/Global 目錄下的 domain.i…

MySQL 事務(一)

文章目錄 CURD不加控制&#xff0c;會有什么問題CURD滿足什么屬性&#xff0c;能解決上述問題&#xff1f;什么是事務為什么要有事務事務的版本支持了解事務的提交方式 事務常見操作方式研究并發場景事務的正常操作事務的非正常情況的案例結論事務操作的注意事項 CURD不加控制&…

CSS面試題匯總

在前端開發領域&#xff0c;CSS 是一項不可或缺的技術。無論是頁面布局、樣式設計還是動畫效果&#xff0c;CSS 都扮演著重要的角色。因此&#xff0c;在前端面試中&#xff0c;CSS 相關的知識點往往是面試官重點考察的內容。為了幫助大家更好地準備面試&#xff0c;本文匯總了…

Java 后端給前端傳Long值,精度丟失的問題與解決

為什么后端 Long 類型 ID 要轉為 String&#xff1f; 在前后端分離的開發中&#xff0c;Java 后端通常使用 Long 類型作為主鍵 ID&#xff08;如雪花算法生成的 ID&#xff09;。但如果直接將 Long 返回給前端&#xff0c;可能會導致前端精度丟失的問題&#xff0c;特別是在 J…

對稱二叉樹的判定:雙端隊列的精妙應用

一、題目解析 題目描述 給定一個二叉樹&#xff0c;檢查它是否是鏡像對稱的。例如&#xff0c;二叉樹 [1,2,2,3,4,4,3] 是對稱的&#xff1a; 1/ \2 2/ \ / \ 3 4 4 3而 [1,2,2,null,3,null,3] 則不是鏡像對稱的&#xff1a; 1/ \2 2\ \3 3問題本質 判斷一棵二叉…

C#數組與集合

&#x1f9e0; 一、數組&#xff08;Array&#xff09; 1. 定義和初始化數組 // 定義并初始化數組 int[] numbers new int[5]; // 默認值為 0// 聲明并賦值 string[] names { "Tom", "Jerry", "Bob" };// 使用 new 初始化 double[] scores …

本地部署Scratch在線編輯器

1、說明 由于在GitHub上沒有找到Scratch源碼&#xff0c;所以只能編寫腳本下載官網相關資源&#xff0c;然后在本地部署。 如果你找到了Scratch源碼&#xff0c;請自行編譯部署&#xff0c;可忽略以下操作。 項目結構&#xff1a;scratch.mit.edu |-- chunks | |-- fetch-w…

Gmsh 讀取自定義輪廓并劃分網格:深入解析與實踐指南

一、Gmsh 簡介 (一)Gmsh 是什么 Gmsh 是一款功能強大的開源有限元網格生成器,廣泛應用于工程仿真、數值模擬以及計算機圖形學等領域。它為用戶提供了從幾何建模到網格劃分的一整套解決方案,能夠有效處理復雜幾何形狀,生成高質量的二維和三維網格,滿足多種數值方法的需求…

Elabscience 精準識別 CD4+ T 細胞|大鼠源單克隆抗體 GK1.5,適配小鼠樣本的流式優選方案

內容概要 CD4 T細胞在免疫調節、自身免疫疾病及腫瘤免疫治療中發揮關鍵作用。Elabscience推出的APC Anti-Mouse CD4 Antibody (GK1.5)&#xff08;貨號&#xff1a;E-AB-F1097E&#xff09;是一款高特異性、低背景的流式抗體&#xff0c;專為小鼠CD4 T細胞亞群檢測優化設計。該…

【RabbitMQ】應用問題、仲裁隊列(Raft算法)和HAProxy負載均衡

&#x1f525;個人主頁&#xff1a; 中草藥 &#x1f525;專欄&#xff1a;【中間件】企業級中間件剖析 一、冪等性保障 什么是冪等性&#xff1f; 冪等性是指對一個系統進行重復調用&#xff08;相同參數&#xff09;&#xff0c;無論同一操作執行多少次&#xff0c;這些請求…

51 單片機頭文件 reg51.h 和 reg52.h 詳解

51 單片機頭文件詳解 51 單片機的頭文件reg51.h和reg52.h是開發中非常重要的文件,它們定義了單片機的特殊功能寄存器 (SFR) 和位地址。以下是對這兩個頭文件的詳細解析: 1. 頭文件概述 reg51.h:針對標準 8051 單片機(4KB ROM, 128B RAM) reg52.h:針對增強型 8052 單片…

前端的面試筆記——JavaScript篇(二)

一、instanceof 在 JavaScript 里&#xff0c;instanceof 是一個相當實用的運算符&#xff0c;它的主要功能是檢查某個對象是否屬于特定構造函數的實例。這里需要明確的是&#xff0c;判斷的依據并非對象的類型&#xff0c;而是其原型鏈。下面為你詳細介紹它的用法和特點&…

”一維前綴和“算法原理及模板

前綴和&#xff0c;就是通過一種方法來求出數組中某個連續區間的元素的和的辦法。我們通常先預處理出來一個前綴和數組&#xff0c;然后把數組中進行元素填充后再進行后續使用。 我們通過一道模板題或許能更加理解其意思。 現在的問題就是&#xff1a;如果我們用暴力枚舉來記錄…

5.13/14 linux安裝centos及一些操作命令隨記

一、環境準備 VMware Workstation版本選擇建議 CentOS 7 ISO鏡像下載指引 虛擬機硬件配置建議&#xff08;內存/處理器/磁盤空間&#xff09; 二、系統基礎命令 一、環境準備 1.VMware Workstation版本選擇建議 版本選擇依據 選擇VMware Workstation的版本時&#xff0c…

spring學習->sprintboot

spring IoC(控制翻轉): 控制:資源的控制權(資源的創建&#xff0c;獲取&#xff0c;銷毀等) 反轉:和傳統方式不一樣(用上面new什么)&#xff0c;不用new讓ioc來發現你用什么&#xff0c;然后我來給什么 DI:(依賴注入) 依賴:組件的依賴關系。如newsController依賴NewsServi…

iOS 閱后即焚功能的實現

iOS閱后即焚功能實現步驟 一、功能設計要點 消息類型支持&#xff1a;文本、圖片、視頻、音頻等。銷毀觸發條件&#xff1a; 接收方首次打開消息后啟動倒計時。消息存活時間可配置&#xff08;如5秒、1分鐘&#xff09;。 安全要求&#xff1a; 端到端加密&#xff08;E2EE&a…

OpenHarmony 開源鴻蒙南向開發——linux下使用make交叉編譯第三方庫——mqtt庫

準備工作 請依照這篇文章搭建環境 OpenHarmony 開源鴻蒙南向開發——linux下使用make交叉編譯第三方庫——環境配置_openharmony交叉編譯-CSDN博客 下載 wget ftp://ftp.gnutls.org/gcrypt/gnutls/v3.5/gnutls-3.5.9.tar.xz 解壓 tar -xf mkdir ./out cd ./out Cmake命…

武漢SMT貼片工藝優化與生產效能提升路徑

內容概要 隨著華中地區電子制造產業集群的快速發展&#xff0c;武漢SMT貼片行業面臨工藝升級與效能提升的雙重挑戰。本文聚焦SMT生產全流程中的關鍵環節&#xff0c;從鋼網印刷精度控制、回流焊溫度曲線優化、AOI檢測系統迭代三大核心工藝出發&#xff0c;結合區域產業鏈特點提…

線程池(ThreadPoolExecutor)實現原理和源碼細節是Java高并發面試和實戰開發的重點

一、線程池核心流程圖 ----------------- | 提交任務 | submit/execute -----------------|v ----------------- | 判斷核心線程數 | < corePoolSize&#xff1f; -----------------|Yes |Nov v [創建新線程] -----------------| 隊列是否滿&a…

學習海康VisionMaster之直方圖工具

一&#xff1a;進一步學習了 今天學習下VisionMaster中的直方圖工具&#xff1a;就是統計在ROI范圍內進行灰度級分布的統計 二&#xff1a;開始學習 1&#xff1a;什么是直方圖工具&#xff1f; 直方圖工具針對輸入灰度圖像的指定ROI區域&#xff0c;輸出該區域的圖像灰度直方…