SubQuery 索引节点(@subql/node)完整演进史:从 0.2.0 到 6.4.6 的核心能力与架构变迁

原创2026-09-30 22:47:291,815 阅读
文章标签:区块链后端

SubQuery 索引节点(@subql/node)完整演进史:从 0.2.0 到 6.4.6 的核心能力与架构变迁

导读

本篇文章以 packages/node/CHANGELOG.md 为骨架,系统梳理 SubQuery 索引节点(@subql/node)从 2020 年底的 v0.2.0 到 2025 年 11 月的 v6.4.6 之间的全部重大版本演进。你会看到索引节点如何一步步具备批量化拉取、数据库缓存、Worker 多线程、未确认区块、多链重索引、项目热升级、POI 可验证索引、字典(Dictionary)加速等能力,并配合当前仓库源码(packages/node/src)印证这些能力在今天的实际落点,形成一份可直接用于升级选型、排障与二次开发的演进图谱。


一、定位:@subql/node 在 SubQuery 体系中的角色

SubQuery 是一个面向 web3 的通用数据索引框架。@subql/node 是其中负责实际运行索引器、连接链节点、拉取区块、执行 mapping 逻辑并把数据写入数据库的索引节点程序(npm 包名为 @subql/node,CLI 入口为 subql-node,见 packages/node/package.json)。

从源码看,它由 NestJS 组织应用:

  • packages/node/src/main.ts 负责解析 yargs 参数并初始化 logger 与 profiler;
  • packages/node/src/yargs.ts 将 CLI 参数配置统一委托给 @subql/node-core/yargs,并注册 testing、force-clean、reindex 三个子命令;
  • packages/node/src/app.module.ts 组合 DbModule、CoreModule、FetchModule、MetaModule 等模块,其中 FetchModule(packages/node/src/indexer/fetch.module.ts)是索引核心,注册了 ApiService、RuntimeService、IndexerManager、blockDispatcherFactory(Worker 分发器工厂)、SubstrateDictionaryService 等关键服务;
  • packages/node/src/init.ts 展示了启动顺序:先初始化项目(projectService.init()),拿到 finalized 高度,再初始化 runtime 与 fetch 服务,最后监听端口。

@subql/node 的大量通用逻辑被下沉到 @subql/node-core(workspace 依赖,见 package.json 第 30 行),CHANGELOG 中大量 "Bump/Sync with node-core" 条目正是这一架构演进的结果。


二、版本演进总览:三大阶段

从 CHANGELOG 的时间线可以清晰划分出三个阶段:

阶段 版本区间 时间 主题
奠基期 0.2.0 – 0.35.x 2020-12 – 2022-05 核心索引链路成型:区块/事件/调用 handler、批量化拉取、数据库 schema、字典、POI、MMR
稳定与拆分期 1.0.0 – 2.x 2022-05 – 2023-05 1.0.0 大版本发布、node-core 拆分、DB 缓存、测试框架、多端点、未确认区块、workers
能力爆发期 3.x – 6.x 2023-06 – 2025-11 多链、项目热升级、历史索引(timestamp/block 双维度)、多字典、CockroachDB、schema 迁移、enum 迁移

[Unreleased] 区块保留,说明该项目遵循 Keep a Changelog + Semantic Versioning 的规范(文档头 4-5 行)。


三、奠基期(0.2.0 → 0.35.x):把索引链路打磨成熟

3.1 从零到一:handler 与批量化(0.2.0 – 0.7.0)

  • v0.2.0(2020-12-22):支持 block handler,SubQuery 表放入独立 db schema,改用 BigInt 替代 BN;
  • v0.3.0:支持 callHandler 与 eventHandler,三大 handler 体系成型;
  • v0.4.0:允许在项目中定义起始区块(start block)、支持从 tarball 加载项目、--local 本地模式;[BREAKING] manifest 规范升级以支持自定义类型;
  • v0.7.0:批量拉取区块(batch fetch blocks),同一区块的所有 handler 执行包进同一个数据库事务——这是索引性能与数据一致性的关键基石。

3.2 沙箱与 API 注入(0.5.0 – 0.15.0)

  • v0.5.0 把沙箱(sandbox)从 IndexerManager 中解耦出来;
  • v0.6.0 支持向沙箱注入并 patch api,增加 specVersion 与 success 过滤器;
  • v0.12.0 增加 @index 索引字段、jsonField 的 jsonb 列、实体关系(v0.11.0)、双 map storage 查询修复;
  • v0.14.0 改为 pull 而非 subscribe 获取新区块高度,规避订阅卡死导致高度失真的问题;
  • v0.15.0 起直到 finalized API 就绪前不拉取区块。

3.3 字典(Dictionary):外部 GraphQL 加速(0.17.0 – 0.22.0)

v0.17.0 是奠基期最重要的性能里程碑:引入外部字典,通过 --network-dictionary=<dictionary_HTTP_url> 或 project.yaml 配置,用外部 GraphQL API 预筛出需要处理的区块,配合 fetch service 的额外区块缓冲区,大幅降低无效区块的处理开销。后续版本持续打磨:

  • v0.20.2 修复字典返回批次中丢失 block height 的问题;
  • v0.20.3/0.26.0 支持自定义数据源使用字典;
  • v1.9.2 字典查询改为事件/交易名大小写不敏感(为兼容 go-dictionary)。

3.4 POI 与 MMR:可验证索引(0.21.0 – 0.23.0)

  • v0.21.0:加入 Proof-of-Index 服务(--proof-of-work,实验性),生成并记录索引工作的哈希;
  • v0.23.0:加入 MMR(Merkle Mountain Range)服务,生成 POI 证明与 MMR 根,存入基于文件的数据库并同步 _poi 表,可通过 --mmr-path 指定本地路径。

这两个特性在今天的 packages/node-core/src/indexer/poi 与 entities/Poi.entity.ts 中仍然活跃,且从 v6.4.4 修复"数组字段导致 POI 问题"可知它一直处于持续维护状态。

3.5 其他奠基期要点

  • v0.16.0/0.16.1:表默认移除 created_at/updated_at,提供 --timestamp-field 开关(v0.25.1 起默认 false);
  • v0.19.0:schema 数组对象转 Jsonb;--help 显示完整选项;
  • v0.25.0:支持枚举类型进 store;新增 force-clean 子命令、unsafe 标志、--port 端口选项(端口被占用时自动寻找可用端口,v0.27.0 起);
  • v0.26.0:--scale-batch-size 按内存自适应调整拉取批量;store 增加 bulkCreate();支持从 JS 加载 chainTypes;
  • v0.28.0:支持从非文件系统位置运行索引器(重构 SubqueryProject)、动态数据源(dynamic datasources)、基于 BlockNumber 的历史 RPC 方法;
  • v0.32.0:切换到 vm2 沙箱(v1.6.0 后再换 x-vm2,v6.4.3 锁定 VM2 版本避免破坏性变更,见 CHANGELOG 2959 号 issue)。

源码印证:manifest 1.0.0 的解析在 packages/node/src/configure/SubqueryProject.ts,通过 parseSubstrateProjectManifest(raw).asV1_0_0 完成;chainTypes 通过 utils/project.ts 的 getChainTypes 加载,对应 v0.26.0/v0.28.0 的 chainTypes 支持。


四、稳定与拆分期(1.0.0 → 2.x):架构重构与性能工程

4.1 1.0.0 大版本与 node-core 拆分

  • v1.0.0(2022-05-11):Major release,奠基期功能全部收敛;
  • v1.8.0 增加 bulkUpdate/bulkGet 到注入 store;
  • v1.9.0 引入 @subql/node-core 包(#1222),链无关逻辑开始下沉;store.getByField 支持 offset/limit;
  • v1.10.0 默认启用历史索引(historical),新增 force-clean 与 reindex 子命令,yargs 文件从 node-core 移回 node。

在今天的仓库中,@subql/node-core 已是独立大包(见 packages/node-core),包含 blockDispatcher、dictionary、POI、storeModelProvider、worker 等全套组件;而 node 包的 subcommands 目录正是 force-clean/reindex/testing 三个子命令的入口。

4.2 数据库缓存(DB Cache):2.0.0 的性能里程碑

v2.0.0 引入完整的 Database cache 体系,至今仍是 node-core 的核心:

  • 记录数达到 --store-cache-threshold(默认 1000)时批量 flush 到数据库,减少事务次数;
  • 通过 --store-get-cache-size(默认 500)决定每个实体在缓存中保留的记录数,读直接命中缓存;
  • --store-cache-async 让写 store 与区块处理异步化(默认开启);
  • v2.9.0 增加 store-cache-upper-limit 限制 store cache 最大尺寸。

对应实现见 packages/node-core/src/indexer/storeModelProvider/storeCache.service.ts,其 "flush" 行为在 v5.10.0 还随 node-core 更新了"完全同步时的新 flush 行为"。

4.3 测试框架:subql-node test(2.0.0)

v2.0.0 同时引入测试框架:开发者可按 *.test.ts 命名约定在 src/tests 或 src/test 目录编写测试用例,直接运行 subql-node test 验证过滤条件与 mapping handler,无需真正索引整个项目。源码入口为 packages/node/src/subcommands/testing.init.ts,它实例化 TestingService(testing.service.ts)执行测试;v3.2.0 修复了 testing 命令缺失依赖的问题,v5.11.0 修复"拉取区块失败时测试结果未正确更新"。

4.4 未确认区块与多端点(1.12.0 – 2.x)

  • v1.12.0:--unfinalized-blocks 开启未确认区块支持(要求启用历史索引)——注意 v6.0.1 已将其在历史索引开启时默认启用;
  • v1.15.0:多链索引支持、字典 auth link 集成;
  • v1.16.0:bypassBlocks 特性,在 project.yaml 中声明要跳过的区块数组(v5.2.7 修复大区块区间设置问题);
  • v1.17.0/v1.18.0:拉取后做 block hash 校验、字典与起始高度校验;
  • v1.19.0:支持 CockroachDB 与 SSL 连接选项;
  • v1.21.0/1.21.1:多端点支持;--sponsored-dictionary 更名为 --dictionary-resolver。

4.5 Worker 多线程(1.6.0 起,实验性→成熟)

  • v1.6.0:--workers=<number> 启用 Worker 线程,将区块拉取与处理搬进 worker,性能可提升最多 4 倍,worker 数量上限为 CPU 核数;同版本加入 --reindex=<blockNumber> 重索引与 block handler 的 modulo 过滤器;
  • v3.0.8 修复 store bulk 方法在 worker 下的失败;v3.4.7 修复 workers 下动态数据源初始化失败;v4.0.1 修复 workers=0 时改用 block dispatcher 而不是报错退出;v6.0.3 修复 worker 导致性能回退的问题。

今天的 Worker 体系分布在 packages/node/src/indexer/worker 与 packages/node-core/src/indexer/worker,且 fetch.module.ts 通过 blockDispatcherFactory 按配置动态选择普通/Worker 分发器。


五、能力爆发期(3.x → 6.x):多链、热升级与数据一致性

5.1 3.x:字典、POI 与日志打磨

  • v3.0.1:项目升级特性(Project upgrades,可在特定高度升级项目)、skipTransactions 与 LightBlock 支持;大量代码迁入 node-core(#1797);
  • v3.3.0:dictionary-query-size 可配置字典查询区块区间;
  • v3.2.0:日志支持负过滤器,如 --debug="*,-SQL" 排除 SQL 日志;
  • v3.5.0:node-core 带来 CSV 导出与 schema 迁移支持;
  • v3.6.1/v3.9.3:修复 POI 负整数生成问题、去掉 subscription triggers 与 notify 函数;node-core 增加重试逻辑。

5.2 4.x:字典 v2 与多字典切换

  • v4.0.0:与 node-core 一起同时支持两个版本字典(v1/v2),且支持多个字典端点,索引器按可用区块自动获取并切换字典(#2257);Polkadot API 升级到 10.12.4;
  • v4.6.0:加入 monitor 服务记录区块索引动作,提升 POI 精度并为 Admin API 提供调试信息;
  • v4.4.x/v4.5.0:chainTypes 支持 hasher 名称字符串;修复缺失 builtins 模块加载。

字典 v1/v2 实现在 packages/node/src/indexer/dictionary/v1 与 v2;v6.3.4 还修复了"字典 v2 在空过滤条件下使用"的问题。

5.3 5.x:时间戳历史索引与缓存开关

  • v5.0.0:BREAKING] 要求索引环境时区设为 UTC(Dockerfile 与 package.json 中同步设置 TZ=utc,见 [package.json 的 start/start:prod 脚本);SubqueryProject 改用 node-core 代码;
  • v5.1.0:支持网络端点配置与请求头指定;
  • v5.3.0:历史索引同时支持按区块高度与按时间戳;新增 --enable-cache 标志,允许在 DB 与 cache 之间选择 IO 方式;
  • v5.5.0:primary-network-endpoint 标志存在时报 "Invalid endpoint" 的问题被修复;
  • v5.7.2/v5.8.0:实现 BlockchainService 匹配新 node-core 架构(#2517);Polkadot API 升到 15。

5.4 6.x:多链重索引、enum 迁移与维护收尾

  • v6.0.0:支持多链项目重索引(multi chain project reindex);v6.0.1 默认启用未确认区块;v6.0.2 不在 worker 中注入 MultichainRewindService;
  • v6.1.0:schema 迁移支持新增 enum 值;
  • v6.3.0:升级 @polkadot/api@^16(注意 metadata 存在破坏性变更);
  • v6.3.2:优化 Docker 镜像体积;v6.3.5 锁定 graphql 相关依赖;
  • v6.4.x:修复 skipTransactions + workers 下取区块时间戳报错(#2978)、模型 updateOnDuplicate 字段计算错误(#2976)、POI 数组字段问题(#2972)、锁定 VM2 版本避免破坏性变更(#2959)。

六、贯穿始终的工程规范与演进规律

6.1 变更管理规范

文档头明确遵循 Keep a Changelog 格式与 Semantic Versioning,每条变更都带 GitHub issue/PR 编号(如 (#2978)),底部维护了从 [Unreleased] 到 v0.2.0 的完整版本对照链接。这为追溯具体修复动机提供了精确锚点。

6.2 版本节奏规律

  • 每周/双周快速迭代:2022 年高峰期几乎每周发版,修复型小版本(如 4.x、5.x 的小数位)占多数;
  • 破坏性变更集中在大版本:0.4.0(manifest)、1.0.0、5.0.0(UTC 时区要求)是三次明显的 BREAKING 节点;
  • 大量 Bump node-core:说明 node 包作为"薄壳",把链无关逻辑持续交给 node-core 复用,这既降低 node 包自身维护成本,也统一了不同链索引器的行为。

6.3 依赖演进路线(Polkadot API)

版本 Polkadot/api 备注
0.6.0 3.6.3 早期
1.13.0 9.7.1 —
1.21.0 10.1.4 —
3.4.0 10.10.1 —
4.0.0 10.12.4 字典 v2 同版本引入
5.8.0 15 —
6.3.0 ^16 metadata 破坏性变更

当前仓库锁定 @polkadot/api@^16.4.7(见 packages/node/package.json),MetaModule 在启动时会记录 sdk 版本(app.module.ts)。


七、关键能力在当前源码中的落点对照

CHANGELOG 特性 当前源码位置
CLI 参数解析与子命令注册 packages/node/src/yargs.ts、subcommands
启动编排(project→runtime→fetch→listen) packages/node/src/init.ts
模块装配(Db/Core/Fetch/Meta) packages/node/src/app.module.ts
项目解析与 chainTypes 加载 packages/node/src/configure/SubqueryProject.ts
索引核心与 Worker 分发器工厂 packages/node/src/indexer/fetch.module.ts
字典 v1/v2 packages/node/src/indexer/dictionary/v1、v2
Runtime(specVersion 管理) packages/node/src/indexer/runtime
API 连接与多端点 packages/node/src/indexer/api.service.ts、apiPromise.connection.ts
测试子命令 packages/node/src/subcommands/testing.init.ts

八、对开发者的实用指引

  1. 选版参照:需要多链重索引 → ≥6.0.0;需要时间戳历史索引 → ≥5.3.0;需要多字典自动切换 → ≥4.0.0;需要默认历史索引 → ≥1.10.0;需要 DB 缓存 → ≥2.0.0。
  2. 升级注意:跨 5.0.0 必须将索引环境时区设为 UTC(镜像与 npm 脚本已默认 TZ=utc);跨 6.3.0 需关注 @polkadot/api@16 对 metadata 的破坏性变更。
  3. 排障线索:遇到 worker 下区块时间戳报错可对照 v6.4.6(skipTransactions + workers);遇到 POI 数组字段问题可对照 v6.4.4;遇到 model 更新字段计算异常可对照 v6.4.5 的 updateOnDuplicate 修复。
  4. 本地运行:subql-node 支持 test、force-clean、reindex 三个子命令;主命令从 main.ts 启动,经 init.ts 完成 bootstrap() 后监听端口(端口被占用自动换用可用端口)。

结语

@subql/node 的 CHANGELOG 是一份浓缩的 web3 索引器工程演进档案:从单节点顺序拉取,到批量事务、DB 缓存、多线程 Worker、外部字典加速、POI/MMR 可验证索引、多链与多字典,再到历史索引与 schema/enum 迁移——每一步都以 issue 编号背书、以 node-core 复用沉淀。对于希望深入 SubQuery 内部实现或评估索引节点能力的开发者而言,这份 CHANGELOG 与 packages/node/src 源码、packages/node-core 通用内核三者对照阅读,是最完整的学习路径。

登录后查看全文
subql