Skip to content
survivorff's blog
Go back

Solana RPC 成本优化:从 $50K 到 $10K 的实战记录

7 min read

一张让我失眠的账单

某个月的某一天,财务发给我一张 RPC 服务商的账单:$52,430

那个月我们的用户量不算大,日活 3-5K,但 RPC 请求量接近 2 亿次。按 Helius 的 business plan 计费,单月花了 5 万多美元。

作为平台方,这个成本吃掉了相当一部分利润。老板盯着问:“能不能降下来?”

接下来两个月,我们把 RPC 月费用从 $50K+ 砍到了 $10K 以内,而且用户体验没有下降。

这篇文章分享具体做法。如果你也在做 Solana 基建,可能有帮助。


为什么 RPC 这么贵

先理解成本结构。Solana RPC 的主要消耗:

1. 查询类调用(占 60%+)

每个活跃用户每分钟可能产生 10-50 次这类调用(同步持仓、检查余额等)。

2. 交易类调用(占 20%)

3. 订阅类调用(占 15%)

4. 其他(占 5%)

高成本的几个”陷阱”:


优化方法总览

按”效果 / 投入”排序,我们实际做了的事:

优化手段                     降本效果     实施难度
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
缓存 token 元数据           30%         低
批量查询代替单次查询         20%         低
WebSocket 替代轮询          15%         中
读写分离 + RPC 分级          10%         中
按用户分层(VIP vs 普通)     8%         中
自建部分节点                  5%         高
去掉非必要的查询              5%         中

累计下来,就是 80% 的降本。


方法 1:缓存 Token 元数据(效果最大)

我们观察到的现象:

用户页面每次刷新,都要查每个持仓 token 的元数据(名字、符号、图标、小数位)。一个活跃用户持仓 30 个 token,每次刷新就是 30 次 RPC 调用。

问题是:这些元数据几乎不会变。Token 一旦创建,名字和符号基本不会改。

做法

  1. 第一次查到某个 token 的元数据后,缓存到 Redis
  2. TTL 设 7 天(偶尔会有更新)
  3. 对于已经”毕业”的 token(市值高、有一定交易量),永久缓存
async function getTokenMetadata(mint: string) {
  // L1: 本地 LRU 缓存(最快)
  const l1 = lruCache.get(mint);
  if (l1) return l1;

  // L2: Redis 缓存
  const l2 = await redis.get(`token:meta:${mint}`);
  if (l2) {
    lruCache.set(mint, JSON.parse(l2));
    return JSON.parse(l2);
  }

  // L3: RPC
  const data = await rpc.getAccountInfo(mint);
  const meta = parseTokenMetadata(data);

  await redis.set(`token:meta:${mint}`, JSON.stringify(meta), "EX", 7 * 86400);
  lruCache.set(mint, meta);

  return meta;
}

效果:token 元数据类请求量下降 95%+。


方法 2:批量查询代替单次查询

Solana RPC 支持 getMultipleAccounts — 一次查最多 100 个账户。但很多代码习惯单个查。

例子:一个用户有 30 个 token,查持仓:

错误做法(30 次请求):

const balances = [];
for (const tokenAccount of userTokenAccounts) {
  const balance = await rpc.getTokenAccountBalance(tokenAccount);
  balances.push(balance);
}

正确做法(1 次请求):

const accountInfos = await rpc.getMultipleAccounts(userTokenAccounts);
const balances = accountInfos.map(parseBalance);

效果:账户查询类请求量下降 60-80%。


方法 3:WebSocket 替代轮询

“检查用户的 token 余额有没有变化”这种场景,我们一开始是每几秒轮询一次。

改成 WebSocket 订阅:

// 订阅用户的 token account 变更
const subscriptionId = rpc.onAccountChange(tokenAccount, (accountInfo) => {
  const newBalance = parseBalance(accountInfo);
  updateUserBalance(userId, mint, newBalance);
});

好处:

注意:WebSocket 有连接数限制,要做好复用 — 一个 WS 连接可以订阅多个账户。

效果:监控类请求下降 70%。


方法 4:读写分离 + RPC 分级

我们用了 3 种不同级别的 RPC:

┌─────────────────────────────────────────┐
│ Tier 1: Premium Staked Connection       │
│   用途:交易提交、狙击、大额交易         │
│   成本:最贵(约 $0.005 / 请求)         │
│   占比:5% 的请求                       │
├─────────────────────────────────────────┤
│ Tier 2: Business Plan                   │
│   用途:实时数据、WebSocket、用户查询    │
│   成本:中(约 $0.0005 / 请求)         │
│   占比:30% 的请求                      │
├─────────────────────────────────────────┤
│ Tier 3: 公共 RPC 或便宜的节点            │
│   用途:非关键查询(统计、后台任务)     │
│   成本:几乎免费                         │
│   占比:65% 的请求                      │
└─────────────────────────────────────────┘

关键是把请求正确分流。常见错误是所有请求都用最贵的 Tier 1 节点。

实现上用一个 RPC Client Pool:

class RpcPool {
  private tier1: RpcClient;  // Staked
  private tier2: RpcClient;  // Business
  private tier3: RpcClient;  // Public

  async call(method: string, params: any[], priority: "high" | "normal" | "low") {
    const client = {
      high: this.tier1,
      normal: this.tier2,
      low: this.tier3,
    }[priority];

    return client.call(method, params);
  }
}

效果:在不影响关键路径体验的前提下,把大部分请求导到便宜的节点,降本 40%。


方法 5:按用户分层

不是所有用户都需要最好的 RPC 服务:

这是一个敏感话题(歧视用户?)。但从商业角度,资源有限时,优先服务贡献最多收入的用户是合理的。

效果:头部用户体验更好,整体成本更低。


方法 6:自建部分节点

终极优化:自己跑一个 Solana validator 或 non-voting RPC 节点。

投入

收益

适合场景

我们最后自建了 2 个节点,专门处理高频查询。

效果:降低了约 20% 的外部 RPC 调用。


反模式:不要做的事

1. 全部自建节点

幻想:“全自建就不用付 RPC 钱了” 现实:维护成本远超预期。节点同步出问题、磁盘爆满、网络抖动…每一个都能让平台瘫痪。

建议:自建补充,不要替代。主力还是用商业 RPC 服务。

2. 只追求最便宜

幻想:“用最便宜的 RPC 省钱” 现实:便宜的 RPC 延迟高、落链率低,用户体验变差,流失更多。

建议:分级使用,关键路径不省钱。

3. 一次性大改造

幻想:“大重构一次全部优化” 现实:风险极高,可能引入新问题。

建议:小步迭代,每次优化一个类别,监控效果,稳定后再下一步。


监控怎么做

降本优化的前提是知道钱花在哪。我们的监控设置:

1. 按 method 统计

每个 RPC 方法的请求量、总耗时、错误率。能看出哪个 API 调用占成本大头。

2. 按业务模块统计

哪个服务(用户查询?交易引擎?监控?)贡献了多少 RPC 请求。

3. 按 tier 统计成本

每天 Tier 1 / Tier 2 / Tier 3 各花了多少钱。

4. 异常告警

请求量突然暴涨?立即告警,可能有代码 bug 或被攻击。


总结

RPC 成本优化的核心思路:

  1. 减少请求 — 缓存 + 批量 + 订阅
  2. 分级使用 — 不是所有请求都值得用最贵的节点
  3. 自建补充 — 大量高频查询自己搞定
  4. 持续监控 — 没有数据,优化是瞎猜

具体效果:我们从月 $50K 降到 $10K,用了 2 个月的工程时间。ROI 非常可观。

如果你也在做 Solana 基建,希望这些经验有帮助。有问题可以在评论区讨论。


关注 X @FrankFu2262 看更多交易系统工程实战。


Share this post on:

Next Post
用 AI 从零搭一个技术博客:完整的过程和心得

继续阅读

如果觉得有用

订阅更新,每次发新文章第一时间收到。不发广告、不搞推销。