链上自动化套利与监控 Agent 可靠性工程:从 RPC 容灾到交易重放防御

封面信息图

在实验室环境下写一个能够发现套利机会或监控大额转账的脚本并不难,只需调几个 ethers.js 接口就能跑起来。但在真实的公链主网恶劣环境中,你的自动化 Agent 必须面对:

  • RPC 节点随机 502/429 限流报错;
  • WebSocket 连接表面维持、实则静默漏块(Silent Disconnection);
  • 链重组(Reorg)引发的虚假套利回滚;
  • 节点重试机制导致的非预期双重下单(Double Spending)。

如果在工程可靠性(Reliability Engineering)上存在漏洞,一次网络抖动就可能导致套利机器人损失数千美元的 Gas,甚至让整个风控系统彻底失明。

本文系统复盘如何打造一套具备 多 RPC 权重路由容灾、心跳自动探活与原子幂等重试机制 的工业级链上 Agent。


一、高可用 Agent 核心容灾拓扑

graph TD
    Agent[Agent 核心决策引擎] --> Router[多 RPC 动态容灾网关 (RPC Pool Router)]
    Router -->|主通道 (低延迟)| RPC1[Alchemy Dedicated WebSocket]
    Router -->|从通道 1 (自动故障转移)| RPC2[Infura Backup Node]
    Router -->|从通道 2 (备用容灾)| RPC3[QuickNode Fallback]
    
    Heartbeat[心跳探活守护协程: 每 5s 校验 latestBlockNumber 递增] -.-> Router
    
    Agent --> MempoolWorker[交易发送器 (带本地 Nonce 状态机 + Redis 分布式锁)]
    MempoolWorker --> MEVRelay[Flashbots / 私有交易节点]

二、多 RPC 动态故障转移与心跳探活实现

// agent/rpcPool.ts
import { createPublicClient, http, fallback, webSocket } from 'viem';
import { mainnet } from 'viem/chains';

export class ResilientRpcManager {
  public client;
  private currentBlock = 0n;
  private lastBlockUpdateTime = Date.now();

  constructor(rpcUrls: string[], wsUrl: string) {
    // 1. 创建具备智能降级与重试机制的 Fallback Transport
    const transports = rpcUrls.map((url) =>
      http(url, {
        retryCount: 3,
        retryDelay: 1000,
        timeout: 5000,
      })
    );

    this.client = createPublicClient({
      chain: mainnet,
      transport: fallback(transports, { rank: true }), // 自动根据节点延迟与健康度动态排序
    });

    // 2. 启动独立的心跳看门狗(Watchdog)
    this.startWatchdog();
  }

  private startWatchdog() {
    setInterval(async () => {
      try {
        const latest = await this.client.getBlockNumber();
        if (latest > this.currentBlock) {
          this.currentBlock = latest;
          this.lastBlockUpdateTime = Date.now();
        } else {
          // 超过 30 秒没有新区块推进,判定为节点网络静默卡死
          if (Date.now() - this.lastBlockUpdateTime > 30000) {
            console.error('🚨 [RPC WATCHDOG ALERT] Block stream stalled! Triggering reconnect...');
            this.handleStallReconnect();
          }
        }
      } catch (err) {
        console.error('Watchdog ping failed:', err);
      }
    }, 5000);
  }

  private handleStallReconnect() {
    this.lastBlockUpdateTime = Date.now();
    // 触发内部节点重选与连接池重建
  }
}

三、本地 Nonce 状态机与防重放并发锁

在多线程或异步事件并发触发套利交易时,直接调用 eth_getTransactionCount 会由于节点广播延迟导致连续两笔交易获取到相同的 Nonce,引发后一笔交易直接覆盖前一笔。

必须在 Agent 本地内存中维护一个严格自增的 Nonce 计数器,并使用 Redis 分布式锁保障原子性:

// agent/txSubmitter.ts
import { redis } from '@/lib/redis';

export class ResilientTxSubmitter {
  private localNonce: bigint | null = null;

  public async getNextNonce(address: `0x${string}`, client: any): Promise<bigint> {
    // 获取分布式锁防止跨进程并发 Nonce 冲突
    const lock = await redis.set(`lock:nonce:${address}`, '1', { nx: true, ex: 5 });
    if (!lock) {
      await new Promise((r) => setTimeout(r, 200));
      return this.getNextNonce(address, client);
    }

    try {
      if (this.localNonce === null) {
        // 初始启动时从链上同步最新 pending 状态的 nonce
        const count = await client.getTransactionCount({
          address,
          blockTag: 'pending',
        });
        this.localNonce = BigInt(count);
      } else {
        // 本地原子累加
        this.localNonce += 1n;
      }

      return this.localNonce;
    } finally {
      await redis.del(`lock:nonce:${address}`);
    }
  }

  public resetNonce() {
    // 发生交易丢包或 Revert 时强制重置本地状态,下次重新从链上校准
    this.localNonce = null;
  }
}

四、生产级可靠性三大黄金准则

  1. 防范链重组(Reorg Buffer)
    对于资金清算类 Agent,在监听到事件后必须将数据压入双端队列,等待至少 2 个后续区块确认;如果在 2 块内发生哈希重组,自动丢弃分叉分支的数据,防止脏数据入库。
  2. 熔断器模式(Circuit Breaker)
    当 Agent 在连续 3 次套利交易中因为滑点或抢跑导致交易 Revert 且 Gas 损失累计超过 0.05 ETH 时,自动触发全局熔断、暂停执行 10 分钟并通过 Webhook 呼叫开发者人工复核。
  3. 日志与指标上报(Prometheus Metrics)
    对每一次 RPC 调用的耗时、错误码、Mempool 延迟进行打点采集,实时大屏展示系统健康状况。

只有在风暴中依然稳如磐石的 Agent,才能在弱肉强食的链上深水区持续捕获属于你的极客战利品。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐