入职 Web3 运维日记 · 第 7 日:消失的 5 万 U —— 归档节点与 Nginx 的智能分流

时间 :入职第 7 天,上午 09:15 天气 :暴雨(大雨拍打着落地窗,像极了此刻混乱的局面) 事件:VIP 资金入账故障

刚到工位,还没来得及把湿透的雨伞收好,财务总监和 Scanner 组长就一脸凝重地围了上来。 "Alen,出大事了。昨晚 11 点,有个 VIP 大户充值了 50,000 USDT。用户发来了 Etherscan 的截图,显示成功了。但我们的财务后台到现在还没显示这笔钱。用户已经在 VIP 群里骂娘了,说我们吞资产。"

我心里"咯噔"一下。在交易所,"资产不可见""服务宕机" 性质更严重,这直接涉及信任危机。

🕵️‍♂️ 1. 上午 09:30:幽灵交易 ------ 为什么 Geth 看不到?

我第一时间检查了我的 Geth 节点:

  • Sync Status : True (已同步)

  • Current Block : 18,550,200 (实时)

  • Peer Count : 55

节点是健康的。我拿到了那个 TX Hash,在 Etherscan 上打开一看:

  • TxHash : 0xab12...

  • From: 用户的 Gnosis Safe 多签钱包地址

  • To: Bybit 充值地址

  • Value: 50,000 USDT

  • Status : Success

看似一切正常。 于是我手动用 curl 问了一下我的节点,想看看节点里到底有没有这笔交易:

复制代码
# 查询交易凭据 (Receipt)
curl -X POST -H "Content-Type: application/json" --data \
'{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0xab12..."],"id":1}' \
http://127.0.0.1:8545

返回结果也是正常的,有 status: 0x1 (成功)。

Scanner 开发指出了问题所在 : "Alen,你看 Etherscan 的 'Internal Txns' 标签页。这笔转账不是普通转账,它是由用户的多签合约内部触发 的。 我们要抓取这种内部转账,不能只看 Receipt,必须调用 debug_traceTransaction 接口,去'重放'这笔交易的执行过程,才能看到它内部调用的 USDT 转账指令。"

"那就调啊!" 我说。

开发无奈地敲下了一行命令:

复制代码
curl -X POST -H "Content-Type: application/json" --data \
'{"jsonrpc":"2.0","method":"debug_traceTransaction","params":["0xab12...", {"tracer": "callTracer"}]}' \
http://127.0.0.1:8545

屏幕上跳出一个冰冷的报错: Error: missing trie node ... (state pruned)

🧠 2. 上午 10:30:运维的失误 ------ 什么是 "State Pruned"?

看到这个报错,我瞬间明白了。这是我 Day 1 埋下的雷。

  • Full Node (全节点) :我搭建的 Geth 使用了 --syncmode snap。为了节省硬盘空间,它只会保留最近 128 个区块(约 25 分钟)的状态

  • Archive Node (归档节点):保留从创世块开始的所有历史状态。

  • 现状:这笔 VIP 充值发生在昨晚 11 点,那是几千个区块之前的事情了。

    • Geth 记得这笔交易"发生过"(有 Receipt)。

    • 但 Geth 已经扔掉了当时的"账本状态"(State Trie Pruned)。

    • 当 Scanner 试图用 debug_traceTransaction 去"重放"昨晚的细节时,Geth 两手一摊:"当时的数据我已经删了,没法重放。"

Scanner 开发叹了口气:"我们需要一个归档节点。但现在同步一个归档节点,至少要半个月,硬盘要 15TB。用户等不了半个月。"

⚡ 3. 下午 01:00:救火 ------ Nginx 的"偷天换日"

现在摆在面前的是个死局:

  1. 用户要钱 :必须立刻通过 debug_trace 拿到数据。

  2. 基建不行:我的本地 Geth 节点不支持查历史 Trace。

  3. 外援太贵:Alchemy 或 Infura 提供归档节点服务,但如果把 Scanner 的所有流量都切过去,每天的账单能把老板吓死(而且有网络延迟)。

Alen 的 AWS 经验上线: "我们不需要把所有流量都切走。我们只需要把**'包含 debug_traceTransaction'** 的请求,转发给 Alchemy,其他的普通请求依然走本地 Geth。"

我打开了 Nginx 配置文件,开始编写一段 Layer 7 智能路由规则

操作实录:

  1. 配置 Upstream

    复制代码
    # /etc/nginx/sites-available/ethereum-rpc.conf
    
    # 1. 本地 Geth (主力,处理 99% 流量)
    upstream local_geth {
        server 127.0.0.1:8545;
        keepalive 64;
    }
    
    # 2. Alchemy 归档节点 (外援,只处理 Trace)
    upstream alchemy_archive {
        server eth-mainnet.g.alchemy.com:443;
        keepalive 8;
    }
  2. 编写路由逻辑 (Lua 都不用,原生 Nginx 搞定) : 利用 Nginx 的 map 模块或者 if 指令检查 request_body(为了稳妥,我用了最直观的 if 写法)

    复制代码
    server {
        listen 8080;
        server_name internal-rpc;
    
        location / {
            # 默认:走本地
            set $target_backend "local_geth";
            set $proxy_url "http://local_geth";
    
            # 智能判断:如果请求体包含 'debug_' 关键字
            # 注意:JSON-RPC 的 method 字段里会有这个词
            if ($request_body ~* "debug_traceTransaction") {
                set $target_backend "alchemy_archive";
                set $proxy_url "https://alchemy_archive/v2/MY_SECRET_API_KEY";
            }
    
            # 代理转发
            proxy_pass $proxy_url;
    
            # 如果是转发给 Alchemy,需要处理 HTTPS 和 Host 头
            if ($target_backend = "alchemy_archive") {
                proxy_ssl_server_name on;
                proxy_set_header Host eth-mainnet.g.alchemy.com;
            }
    
            # 增加调试头,方便我知道这笔请求走了哪条路
            add_header X-Served-By $target_backend always;
        }
    }
  3. 重载 Nginxsudo nginx -t && sudo nginx -s reload

验证时刻: 我对开发喊道:"再试一次!" 开发再次点击了重试按钮。

我盯着 Nginx 的 Access Log:

复制代码
[13:15:01] POST / - 200 OK - body: "eth_blockNumber" -> local_geth
[13:15:02] POST / - 200 OK - body: "debug_traceTransaction..." -> alchemy_archive

成功了! 普通的查询瞬间由本地返回,而那笔棘手的 Trace 请求被 Nginx 精准地"偷运"到了 Alchemy。 几秒钟后,财务后台刷新:[+50,000 USDT]。 开发松了一口气:"入账了,Scanner 扫到内部交易了。"

🏗️ 4. 下午 03:30:长远之计 ------ 部署 Erigon

虽然用 Alchemy 救了急,但长久依赖第三方既不安全也不合规。 组长拍板:"Alen,这次事故提醒我们,归档数据是刚需。去搭一个自建的归档节点。"

Geth 的归档模式(Archive Mode)效率极低,数据膨胀到 15TB 且难以维护。 我决定使用 Erigon。这是专门为高性能和低存储设计的以太坊客户端。

AWS 选型调整: Erigon 对磁盘 IO 的要求比 Geth 还要变态,而且主要瓶颈在顺序读写大容量

  • 放弃 EBS:即便是 io2,存 10TB+ 的成本也太高了。

  • 选择本地盘 :我申请了一台 AWS i4i.2xlarge 实例。

    • 特点 :自带 3,750 GB 的 AWS Nitro SSD(本地 NVMe)。

    • RAID 0:我开了 4 台这样的机器或者挂载多块盘,组了 RAID 0,凑够 15TB 的超高速本地存储。

启动 Erigon:

复制代码
# 简单的启动命令,但背后是几十 TB 数据的同步
./erigon \
  --datadir /data/erigon \
  --chain mainnet \
  --private.api.addr=localhost:9090 \
  --torrent.download.rate=500mb # 拉满带宽下载初始数据

看着屏幕上 Erigon 开始像推土机一样同步区块,我知道,等它大概 5 天后同步完成,我们就拥有了**"上帝视角"**------可以查阅以太坊历史上任何一笔交易的微观细节。


📝 Day 7 总结

晚上 7:00,雨停了。 那笔 50,000 U 的资金已经安全地在公司的冷钱包里躺着了。

Alen 的复盘:

  1. 认知升级:Full Node ≠ Archive Node。大部分时候全节点够用,但涉及多签合约、复杂的 DeFi 套利分析,必须要有 Trace 能力。

  2. 运维价值 :今天如果我只是个会敲 Geth 命令的运维,这事儿就僵住了。正是因为我懂 Nginx 的高级配置 (Lua/If)HTTP 协议,才能在不改代码的情况下,用"路由"解决了数据源的问题。

"在 Web3,数据就是资产。 有时候你缺的不是代码,而是看穿数据迷雾的那双眼睛(Archive Node)。"


📚 附录:Alen 的 Web3 运维错题本 (Day 7)

📖 第一部分:核心概念解析 (Glossary)

1. Internal Transaction (内部交易)
  • 别名:Message Call / Internal Message。

  • Alen 的理解

    • 外部交易 (External Tx):像是我直接给你发微信红包。微信系统(区块链)直接记录"Alen -> Henry : 100元"。

    • 内部交易 (Internal Tx):像是你把钱存进了"自动理财机器人"(智能合约)。然后机器人根据代码逻辑,自动转了 50 元给 Henry。

    • 关键点 :区块链的区块体(Block Body)里只记录 你和机器人之间的交互。机器人转给 Henry 的那 50 元,是代码执行的过程(副作用),不会作为一笔独立的 Transaction 被记录。

  • 运维痛点 :普通的 eth_getBlocketh_getTransactionReceipt 接口,看不到 这 50 元。必须用 trace 接口重放执行过程才能抓到。

2. Archive Node (归档节点) vs Full Node (全节点)
  • Full Node (默认 Geth)

    • 存什么:所有区块头、所有交易体。

    • 丢什么丢弃历史状态 (State)。它只保留最近 128 个块(约 25 分钟)的"世界状态快照"。

    • 比喻 :它像一本历史书,记录了哪年哪月发生了什么事,但如果你问它"100年前那场战争中,士兵当时口袋里有多少钱?",它回答不了,因为它没存那么细的快照。

  • Archive Node

    • 存什么:一切。存下了宇宙诞生以来每一秒钟的所有快照。

    • 代价:硬盘空间是全节点的 10 倍以上(目前约 15TB+)。

3. State Pruning (状态修剪)
  • 定义:Geth 为了节省硬盘,会自动删除旧的 Merkle Trie 节点数据。

  • 报错含义missing trie node = "你要查的数据树枝已经被我剪掉了"。

  • 场景 :当你试图对一个 3 天前的区块做 debug_traceTransaction 时,Geth 需要读取 3 天前那一刻的账户余额和代码状态。如果这些数据被 Pruned 了,Trace 就会失败。

4. Erigon (新一代客户端)
  • 定位 :Geth 的最强竞争对手,专为 归档节点 设计。

  • 优势

    • 存储结构:它不像 Geth 那样把数据存成复杂的树(Trie),而是尽量"扁平化"存储。

    • 效率:同样的归档数据,Geth 可能需要 20TB 且索引很慢,Erigon 可能只需要 2-3TB(非归档)或更少空间,且同步速度极快。

  • Alen 的选择:在需要跑归档节点时,Erigon 是目前的行业标准;跑普通节点时,Geth 依然是主流。


❓ 第二部分:关键技术问答 (Q&A)

Q1: 既然 Alchemy 这种第三方服务能查 Trace,为什么我们不把所有流量都切过去?还要自建节点?
  • A: 成本与隐私的双重考量。

    1. 成本 (Cost) :Alchemy 的收费模式是按 Compute Units (CU) 计算的。

      • 普通的 eth_blockNumber 很便宜。

      • debug_traceTransaction 极贵(消耗资源大)。

      • 如果 Scanner 每秒几百个请求全走 Alchemy,一个月的账单可能比雇两个 Alen 还要贵。

    2. 隐私 (Privacy):把所有查询请求发给第三方,意味着第三方知道你的钱包地址、你的业务逻辑、你的资金流向。对于大交易所来说,这是核心商业机密。

    3. 策略混合架构。平时用自建节点(便宜、隐私),遇到自建节点搞不定的(如历史 Trace),再用 Nginx 路由给 Alchemy(救急)。

Q2: 为什么那笔 50,000 U 的交易在 Etherscan 上显示 Status: Success,但 Scanner 还是没扫到?
  • A: "Success" 只代表代码跑通了,不代表钱到了你口袋。

    • Status: Success 意味着:这笔交易没有因为 Gas 不足或代码报错而 Revert。

    • Scanner 的逻辑:Scanner 通常是去过滤 Logs(事件日志)或者看 Value 字段。

    • 盲区:内部交易(Internal Tx)产生的转账,既不在 Value 字段(那是 0),有时也不一定触发标准的 Transfer Log(取决于合约怎么写的)。

    • 结论:运维不能只看 Status,必须深入理解业务方到底依靠什么字段来判断"入账"。

Q3: 为什么部署 Erigon 要用 AWS i4i 实例(本地盘),而不用之前的 io2 EBS?
  • A: 物理瓶颈的突破。

    • EBS (io2) :虽然快,但它本质上是 网络存储 (Network Storage)。你的 EC2 和硬盘之间隔着网线。虽然延迟低,但在处理 15TB 数据的海量小文件索引时,网络延迟会被放大。且 15TB 的 io2 价格极其昂贵(数万美金/月)。

    • Instance Store (本地 NVMe)i4i 系列的硬盘是 物理插在主板上的

      • IOPS:数百万级。

      • 延迟:微秒级。

      • 缺点数据易失。如果关机(Stop)或硬件故障,数据就没了。

    • 运维决策 :归档节点本来就是从链上同步下来的数据,丢了可以重跑(虽然慢)。为了极致的同步速度和性价比,本地 NVMe 是唯一选择

Q4: Nginx 的 if ($request_body ~* "debug_") 这种写法性能好吗?
  • A: 不是最好,但是最快见效的。

    • 在 Nginx 里读取请求体(Request Body)并做正则匹配,确实会消耗一点 CPU,且这要求 Nginx 必须先把整个 Body 读进内存。

    • 但对于救火来说:这个损耗完全可以接受。相比于重写 Scanner 代码或者等待半个月同步节点,牺牲一点 Nginx 性能来实现**"无代码侵入的路由分流"**,是性价比最高的运维手段。

相关推荐
晚风吹长发1 小时前
初步了解Linux中的POSIX信号量及环形队列的CP模型
linux·运维·服务器·数据结构·c++·算法
ETFOption2 小时前
ETF期权实战手册:从策略构建到动态管理的完整流程
区块链
郝亚军2 小时前
Ubuntu启一个http server,通过terminal测试通不通
linux·运维·ubuntu
ccino .2 小时前
【官方最新VMware workstation pro获取】
运维·网络安全·自动化
草莓熊Lotso4 小时前
Linux 基础 IO 初步解析:从 C 库函数到系统调用,理解文件操作本质
linux·运维·服务器·c语言·数据库·c++·人工智能
EverydayJoy^v^10 小时前
RH134学习进程——十二.运行容器(1)
linux·运维·容器
b***251110 小时前
电池组PACK自动化生产线的关键流程与核心优势
运维·自动化
哲伦贼稳妥12 小时前
职场发展-遇到以下情况请直接准备后手吧
运维·经验分享·其他·职场和发展
Exquisite.13 小时前
企业高性能web服务器(4)
运维·服务器·前端·网络·mysql