TON liteserver 一直报 not ready?成因分析与彻底解决方案
TON liteserver 返回 not ready 或 ADNL 超时?从公共 global-config 节点的根因讲起,用重试、端点轮换和 TONNode hosted 密钥彻底消掉这个报错。
liteserver not ready:明明只发了个简单请求,回来的却是“not ready”
你在写一个智能体,任务很简单:查一下钱包余额,或者调用合约的某个 get 方法。代码没错,地址没错,liteserver 配置也是从官方 global-config.json 里拿的。可你时不时就会撞上 not ready,或者干脆什么都收不到——连接直接挂起,最后以 ADNL 超时收场。更烦的是它并非每次都能复现:早上一切正常,一到高峰就出问题。是不是很熟悉?这不是你代码的 bug,也不是“TON 挂了”,而是全局配置里公共 liteserver 的可预期行为。下面我们来拆解 TON liteserver not ready 的成因,看看客户端侧哪些手段真正有用,哪些没用。
TON liteserver 的“not ready”和 ADNL 超时到底是什么意思
not ready 是 liteserver 的直白回答:“我还没同步完,暂时没法回复你。”TON 的区块链分两层:主链(masterchain)和 basechain(0 号工作链),后者又切分成若干分片链(shardchain)。主链好比一本书的目录,分片链才是装着交易和账户状态的正文章节。节点经常会先拿到主链的最新区块头,之后才慢慢补齐对应的分片区块。在这个时间窗口里,主链领先于 basechain,而账户状态存在于最新的分片区块里——此刻还查不到。于是节点老老实实回一句 not ready,而不是把过期或不完整的数据塞给你。
ADNL 超时是同一种病的另一个症状。ADNL 是 TON 的原生传输协议,liteserver 和客户端之间就靠它通信(这里面完全没有 HTTP)。节点过载时,它干脆就不在规定的时间窗口内回应 ADNL 请求,客户端还没走到业务逻辑就先超时断开了。
这里千万别把层次搞混。not ready 和 ADNL 超时发生在 liteserver 的原生 ADNL 协议层。它和 HTTP 的 429 Too Many Requests 不是一回事——后者是 toncenter、tonapi.io 这类 HTTP 网关在你超出限额时返回的。不同的层,不同的状态码,不同的成因。如果你正在跟 429 搏斗,那是另一个话题:toncenter 429 修复指南。至于 TON 群聊里流传的“228 错误”梗——那只是社区玩笑,并不是真实的错误码;liteserver 从来不会这么回复。
为什么全局配置里的公共 liteserver 一到高峰就掉链子
问题的根源相当平淡:ton.org/global-config.json 里的 liteserver 是共享且限流的。这是一个公共资源,全世界成千上万的开发者、机器人、索引器和智能体都在同时访问它。这样的资源有三个系统性短板:
- 共享负载。 你和整个生态在分同一个池子。高峰期节点要么追不上全网最新区块(于是
not ready),要么干脆不按时回应(ADNL 超时)。 - 没有深度历史。 公共节点不保存深度归档。如果你要按
lt/hash找一笔老交易,它可能已经不在了——关于历史数据有单独一篇 lt 与 hash 详解。 - 零保障。 这是“按原样提供”的资源。没有人给你优先级,也没有人向你承诺吞吐量:今天走运,明天未必。
也就是说,not ready 不是“等一等就过去”的偶发事件,而是共享资源在高负载下的必然行为。无论你的代码写得多漂亮,都没法让别人那台过载的节点同步得更快。
客户端侧的修补:重试、端点轮换和超时调优
在动基础设施之前,先把客户端能做的做到位。这些手段确实管用,但天花板很明显——节点终究还是共享的。
1. 指数退避重试
not ready 往往是瞬态的:200–800 毫秒之后,同一台 liteserver 可能已经应用了你要的分片区块。简单的递增延迟重试就能消掉相当一部分报错。
async function withRetry<T>(fn: () => Promise<T>, tries = 4): Promise<T> {
let lastErr: unknown;
for (let i = 0; i < tries; i++) {
try {
return await fn();
} catch (e) {
lastErr = e;
// 只重试 'not ready' 和 ADNL 超时,业务错误不重试
await new Promise((r) => setTimeout(r, 200 * 2 ** i));
}
}
throw lastErr;
}
2. 端点轮换
池子里多放几台配置里的 liteserver,当前这台一旦返回 not ready 或者超时,就立刻切到下一台。这台落后了,旁边那台也许已经追上来了。
3. 放宽超时
默认的 ADNL 超时对一台过载的公共节点来说有时太苛刻。适当加几秒余量,可以减少误判导致的断连。但如果把超时拉到天荒地老,你只是在囤积挂起的请求——这不是治疗,是麻醉。
还有一个很实用的小技巧:在真正的请求之前先做一次轻量健康检查。get_masterchain_info(主链最新区块)是最理想的选择:节点一旦追上全网进度,最先给出最新 seqno 的就是这个操作;而只有当节点连主链最新区块都没追上时,它才会返回 not ready。拿到了最新的 seqno,说明节点在线,可以放心执行 get_account_state、get_balance、run_get_method。
说句实话: 重试 + 轮换 + 超时调优能把错误率往下压,却消除不了根因。公共节点的过载是 by design 的——你只是敲门的姿势更礼貌了,门后排的还是同一条长队。其他访问 TON 的方式,都收在这篇 2026 年 toncenter 替代方案盘点 里。
不自建节点的解法:TONNode hosted 密钥 + 我们自己的 liteserver
想根治 not ready 只有一条路——别再去挤公共节点。而自己搭建和维护一台 TON 节点又贵又折腾:同步、磁盘、升级、监控,一样都少不了。折中方案是:不去挤公共池子,而是凭自己的密钥拿到有保障的吞吐量和优先访问权。
TONNode 是面向 TON 的 hosted MCP 服务器。MCP(Model Context Protocol)是 AI 智能体(Claude、Cursor、ChatGPT/Codex 以及任何 MCP 客户端)调用工具的标准协议。你的代码不必再解析全局配置、围着 not ready 跳舞——智能体直接调用现成的工具,工具背后是 hosted 端点 https://mcp.tonnode.io/mcp,配上你的 Bearer 密钥。你得到的是有保障的吞吐量,而不是公共队列。
@tonnode/mcp 是开源包(MIT 协议,npm 和 GitHub tonnode/mcp 上都有),走的是 TON 原生 ADNL 协议,中间没有任何 HTTP 层。也就是说,你没有把传输换成慢吞吞的 HTTP 网关,而是留在同样纯粹的 ADNL 上——只不过你的密钥带来了优先访问权。
日常诊断和读链,这几个工具最常用:
get_masterchain_info—— 主链最新区块,天然的健康检查。get_account_state—— 账户状态、标志位和最近一笔交易。get_balance—— 以 GRAM 计的余额。run_get_method—— 合约的任意只读 get 方法。
如果你刚开始接触 TON 上的 MCP,可以先读这篇 TON MCP 入门指南。
怎么接入:本地 npx,或带密钥的 hosted 端点
本地免费跑
全套读链工具开箱即用——本地运行、走公共配置,不用绑卡,也不用密钥:
{
"mcpServers": {
"ton": {
"command": "npx",
"args": ["-y", "@tonnode/mcp"]
}
}
}
这对开发和本地实验来说足够好。但要记住:本地 npx 底层访问的仍然是那些公共 liteserver,所以它救不了高峰期的 not ready——它省掉的是折腾依赖的时间,给你的是一套统一的工具接口。
hosted + 密钥
要彻底告别公共节点,把传输切到 HTTP-MCP,带上你自己的 Bearer 密钥(工具调用本身仍走 ADNL 打到我们的节点上):
{
"mcpServers": {
"ton": {
"type": "http",
"url": "https://mcp.tonnode.io/mcp",
"headers": { "Authorization": "Bearer tn_live_…" }
}
}
}
配好之后智能体怎么用
接入之后,给智能体一段普通的提示词就够了——工具它自己会挑:
先调
get_masterchain_info做健康检查。然后对EQC…调get_account_state——给我看账户状态和最近一笔交易。最后对同一地址调get_balance。
底层就是这样一条链:get_masterchain_info(节点在线,且已追上最新区块)→ get_account_state(状态、标志位、最近一笔交易)→ get_balance(GRAM 余额)。不用再围着别人的队列写重试——请求直接打在有保障的吞吐量上。顺带一提,GRAM 是 Toncoin 改名后的名字(2026 年 6 月完成改名);网络本身仍然叫 TON。
免费的 Hobby 密钥(60 次请求/分钟)登录后立刻发放,无需绑卡。随着规模增长再升级:Pro —— $29/月,300 次请求/分钟;Scale —— $199/月,1200 次请求/分钟。一个重要细节:所有套餐都能用全部 16 个 TONNode 工具——你付费买的只是吞吐量,而不是功能。
独享 liteserver:按需人工开通,不是自助服务
有时候 hosted 套餐也不够用,你需要一台独享(single-tenant)liteserver——只跑你的流量,完全没有邻居。这个选项确实存在,但说实话:它不是自助服务。仪表盘里没有“开通 single-tenant”的按钮——需要人工对接:给我们写信,聊聊你的负载和配置。
关于历史深度,还有一条必须坦白的说明。TONNode 的归档节点目前还在同步中,暂不对外提供服务。“归档深度”是路线图上的一项,而不是已上线的功能。如果你今天就必须拿到全量深度历史,请另行规划。哪些已经就绪、哪些还在计划中,见路线图。
小结
not ready= 节点未同步完成:主链领先于分片,最新分片区块里的账户状态暂时还查不到。- 全局配置里的公共 liteserver 共享且限流:
not ready、ADNL 超时、没有深度历史。别把它和 toncenter/tonapi 的 HTTP 429 混为一谈——那是另一层的事。 - 客户端侧修补(指数退避重试、端点轮换、超时调优)能降低错误率,但消除不了根因。
get_masterchain_info是你的健康检查:只有节点连主链最新区块都没追上时,它才会亮红灯not ready。- 真正的治疗方案,是从共享资源迁到有保障的吞吐量上。
免费领一把 Hobby hosted 密钥,从此不用在公共节点上跟“not ready”捉迷藏 → tonnode.io/dashboard?plan=hobby