Neon 源码目录结构全解析:从 compute 到 storage 的 Serverless Postgres 代码地图
2026/9/13 16:56:23 网站建设 项目流程

Neon 源码目录结构全解析:从 compute 到 storage 的 Serverless Postgres 代码地图

【免费下载链接】neonNeon: Serverless Postgres. We separated storage and compute to offer autoscaling, code-like database branching, and scale to zero.项目地址: https://gitcode.com/GitHub_Trending/ne/neon

本文以 docs/sourcetree.md 为骨架,逐层拆解 Neon(Serverless Postgres)仓库的源码树布局:每一个核心子目录承担什么职责、与计算/存储分离架构的关系、以及如何围绕这份目录展开日常开发——包括 Rust 依赖管理(cargo-hakari)、Cargo deny 安全审计、Python/poetry 测试环境搭建和 CLion 调试工程配置。读完本文,你将能在这份庞大仓库中快速定位到任一模块的源码、测试与配置,并具备直接上手开发的最小操作路径。

目录总览:一个仓库,三种语言,一条完整的计算-存储分离链路

Neon 将 PostgreSQL 的计算与存储分离:计算节点(Compute Node)负责执行 SQL,存储层由 pageserver、safekeeper 与 storage_broker 等组件组成。源码树的每个子目录都对应这条链路上的一个环节,同时混编了 Rust(核心服务)、C(PostgreSQL 扩展)、Python(集成测试)三种语言。

从仓库根目录的 Cargo.toml 可以看到,Rust workspace 当前共包含 40 余个 crate,覆盖compute_toolscontrol_planepageserverproxysafekeeperstorage_brokerstorage_controllerstorage_scrubber以及libs/下大量共享库。下面按字母序逐目录说明其定位。

storage_broker:存储节点之间的无状态消息中枢

storage_broker 是 Neon 存储 broker,为 safekeeper 与 pageserver 提供消息传递能力。它要解决两个核心问题(详见 docs/storage_broker.md):

  1. 让 safekeeper 与 pageserver 互相感知"谁持有哪些 timeline、这些 timeline 的最新状态";
  2. 避免存储节点之间建立 O(n²) 的全互联连接。

broker 被谁使用:pageserver 通过它确定"最先进且存活"的 safekeeper 以拉取 WAL;safekeeper 通过它同步 timeline 状态——推进remote_consistent_lsnbackup_lsn,以及决定由谁把 WAL 卸载到 S3。

从技术上它是一个基于 tonic(gRPC)的无状态 pub-sub 消息 broker。由于无状态,故障转移可交由 Kubernetes 完成;源码中虽未内置复制机制,但实现上并不难扩展。

gRPC 服务定义见 storage_broker/proto/broker.proto,核心 RPC 有四个:

  • SubscribeSafekeeperInfo:订阅 safekeeper 状态更新(可订阅全部或指定 timeline);
  • PublishSafekeeperInfo:safekeeper 以流式方式推送自己的 timeline 状态;
  • SubscribeByFilter:按消息类型 + tenant/timeline 过滤订阅;
  • PublishOne:发布单条消息。

目前最主要的消息类型是SafekeeperTimelineInfo:每个 safekeeper 会定期为每个活跃 timeline 推送状态,其中包含termlast_log_termflush_lsncommit_lsnbackup_lsnremote_consistent_lsnsafekeeper_connstrhttp_connstr以及可选的availability_zone等字段。broker 在 gRPC 服务的同一端口上还提供/metrics

客户端连接细节:默认监听地址为127.0.0.1:50051(见 storage_broker/src/lib.rs),默认 keepalive 间隔 5000ms、连接超时 5s。连接是懒加载的——首次请求才真正建连;若 endpoint 以https://开头会自动启用 TLS。

调试技巧:可以用 grpcurl 直接查看当前被推送的值:

grpcurl -proto broker/proto/broker.proto -d '{"all":{}}' -plaintext localhost:50051 storage_broker.BrokerService/SubscribeSafekeeperInfo

storage_controller:管理 pageserver 集群与多分片租户

storage_controller 是 Neon storage controller,负责管理一组 pageserver,并向外部暴露统一 API,使一个被切成多个 shard 的租户(many-sharded tenant)可以被当作单一实体来管理。它与 broker 的分工不同:broker 解决节点间信息分发,controller 解决集群编排、租户分片与节点调度。

control_plane:本地控制平面

/control_plane 是本地控制平面,提供启动、配置、停止以本地进程方式运行的 pageserver 与 postgres 实例的功能,主要服务于集成测试和本地安装的 CLI 工具。

从源码看(control_plane/src/lib.rs),它内部按组件拆分为多个模块:background_process(后台进程管理)、endpoint(计算节点端点)、local_env(本地环境布局)、pageserversafekeeperpostgresql_conf(PostgreSQL 配置生成)与storage_controller。以 pageserver 为例,control_plane/src/pageserver.rs 中的start()即负责在本地拉起一个 pageserver 进程,这正是测试夹具(如 test_runner/fixtures/pageserver)的底层实现基础。

docs:特性与概念文档

/docs 存放 Neon 特性与概念的文档,目前主要是面向开发者的文档。它与本篇文章直接相关的重要主题文档包括:

  • docs/pageserver-services.md:pageserver 内部各服务线程(Page Service、WAL Receiver、Backup Service 等)的架构说明;
  • docs/walservice.md:WAL service(safekeeper 集群)的整体设计;
  • docs/storage_broker.md:上文 broker 的详细说明;
  • docs/safekeeper-protocol.md:safekeeper 共识协议的详细描述。

pageserver:Neon 存储服务

/pageserver 是 Neon 的存储服务(storage service),承担多项职责(见 docs/sourcetree.md 与 docs/pageserver-services.md):

  • 存储并管理数据;
  • 生成用于引导 ComputeNode 的 tarball;
  • 响应来自 Compute Node 的GetPage@LSN请求;
  • 从 WAL service 接收 WAL 并解码;
  • 重放适用于 pageserver 所维护 chunk 的 WAL。

其内部由多个线程/服务组成:Page Service监听来自计算节点的 GetPage@LSN 请求(每个连接一个线程,使用 libpq 协议通信);WAL Receiver使用 PostgreSQL 物理流复制协议连接 safekeeper 并持续接收 WAL;Backup Service负责把恢复数据外置到远程存储(目前支持本地文件系统、AWS S3、Azure,且默认关闭,可通过remote_storage配置开启)。

pageserver 的核心抽象是Repositorytrait(见 docs/pageserver-services.md),每个租户一个 Repository,存放在.neon/tenants/<tenant_id>目录下。每个 Repository 内含多个 Timeline(与 PostgreSQL WAL timeline 无关,更接近"分支 branch"的概念,与 branch 一一对应)。此外还有 WAL redo manager,它通过一个运行在 Neon 特殊 wal-redo 模式下的 Postgres 进程来重放 WAL 记录。

proxy:Postgres 协议代理/路由器

/proxy 是 Postgres 协议代理/路由器:监听 psql 端口,可通过外部服务校验认证,并创建新的数据库与账户(在本项目中即 control plane API)。它面向 serverless 场景承担连接路由、认证转发与计算节点调度入口的角色。

test_runner:基于 pytest 的集成测试

/test_runner 存放用 Python 编写、基于 pytest 框架的集成测试。测试覆盖端到端链路:fixtures/中封装了 pageserver、safekeeper、endpoint 的测试夹具(如 test_runner/fixtures/neon_fixtures.py),regress/下有大量回归测试,performance/下则包含 TPC-H、pgvector、large_synthetic_oltp 等性能测试,另有logical_repl/cloud_regress/sql_regress/等专题测试目录。

vendor/postgres-v14 与 vendor/postgres-v15:定制化 PostgreSQL 源码

/vendor/postgres-v14/vendor/postgres-v15是各版本 PostgreSQL 源码树,附带 Neon 所需的修改。当前仓库根目录 Makefile 中POSTGRES_VERSIONS = v17 v16 v15 v14,即 Neon 目前支持在 PostgreSQL 14 到 17 上构建运行;构建产物默认安装到pg_install/,编译参数由 postgres.mk 引入。

pgxn/neon:核心存储管理扩展

/pgxn/neon 是 PostgreSQL 扩展,实现了存储管理器 API(storage manager API)以及与远程 pageserver 的网络通信。它位于计算节点内部,负责把 PostgreSQL 的页面读写请求转译为对远端 pageserver 的GetPage@LSN调用,并承载 WAL 提议(walproposer)等能力。扩展的核心 C 源文件包括 pgxn/neon/neon.c、pgxn/neon/libpagestore.c、pgxn/neon/walproposer.c 等,扩展版本升级脚本以neon--1.0.sqlneon--1.x--1.y.sql的形式维护在 pgxn/neon/ 目录中。

pgxn/neon_test_utils:测试与调试专用扩展

/pgxn/neon_test_utils 是包含测试与调试所需函数的 PostgreSQL 扩展,其 SQL 定义见 pgxn/neon_test_utils/neon_test_utils--1.3.sql,实现位于 pgxn/neon_test_utils/neontest.c。这类"测试专用扩展"模式允许在不污染生产代码的前提下注入故障、观测内部状态。

pgxn/neon_walredo:pageserver 内的 WAL 重放进程库

/pgxn/neon_walredo 是将 Postgres 作为 pageserver 中"WAL redo process"运行的库。pageserver 需要按需把 WAL 重放成页面版本以满足 GetPage@LSN,这个重放过程就交给一个以特殊模式启动的 Postgres 进程(pgxn/neon_walredo/walredoproc.c),pageserver 通过管道与其通信。

safekeeper:WAL 服务(接收与分发中心)

/safekeeper 是 Neon 的 WAL service:从主计算节点接收 WAL,再流式传给 pageserver。正如 docs/walservice.md 所描述,它充当近期生成 WAL 的暂存区与再分发中心

架构要点:

  • 主 Postgres 把 WAL 流式推送给 safekeeper,并把它当作(同步)副本对待;主节点使用复制槽防止在 WAL 尚未送达 WAL service 前就将其丢弃;
  • 数据流为Compute node → WAL Service(多个 safekeeper)→ Pageserver
  • 一条 WAL 记录只有当多数派 safekeeper收到并落盘后才算持久化,基于Paxos的共识算法管理 quorum,并保证任意时刻只有一个主节点在向 quorum 推送 WAL;
  • 主节点采用"push"方式连接 safekeeper,这与传统流复制中副本主动发起连接不同;负责推送的组件叫WAL proposer,是运行在主 Postgres 中的后台进程(实现见 pgxn/neon/walproposer.c);
  • pageserver 使用 Postgres 主备之间相同的流复制协议连接 safekeeper 拉取 WAL;测试场景下也可让 pageserver 直连主 PostgreSQL。

关于"为什么要单独的 WAL service":pageserver 是可能丢失的单点,而 Neon 主容错存储是 S3,不希望事务提交被 pageserver 阻塞。WAL service 充当近期数据的临时容错存储,待 WAL 与页面写入 S3 后即可裁剪(trim)。共识算法的形式化规格见 safekeeper/spec/ 下的 TLA+ 规范文件。

workspace_hack 与 libs:依赖固定与共享库

/workspace_hack 这个 crate 只用于固定(pin down)部分依赖,自动化工具是 cargo-hakari。其作用是统一 workspace 中所有 crate 的依赖特性组合,避免因特性在不同 crate 间不一致导致重复编译。

/libs 把多个粒度较小的 Neon 辅助 crate 聚合在一个屋檐下,包括(均为 workspace 成员,见 Cargo.toml):

  • /libs/postgres_ffi:与 PostgreSQL 文件格式交互的实用函数,内含从 PostgreSQL 头文件复制来的常量;
  • /libs/utils:在仓库内其他 crate 间共享的通用辅助代码,未来有进一步模块化的空间;
  • /libs/metrics:帮助服务器暴露 Prometheus 指标;
  • 此外还有pageserver_apisafekeeper_apicompute_apiwalproposerwal_decoderremote_storagepostgres_backendpq_protohttp-utilstracing-utilstenant_size_model等,共同支撑各服务的 RPC 定义、WAL 解析、远端存储抽象等基础能力。

开发工作流:Rust 依赖管理、安全审计与构建

添加 Rust 依赖:同步 hakari manifest

当你新增一个 Cargo 依赖时,需要运行以下命令并提交更新后的Cargo.lockworkspace_hack/(可能没有变化,这也没关系):

cargo hakari generate cargo hakari manage-deps

如果尚未安装 hakari(出现error: no such subcommand: hakari),先安装:

cargo install cargo-hakari

审计第三方 Rust 依赖

Neon 使用 Cargo deny 检查依赖图是否符合要求——检测安全漏洞、匹配许可证,并确保 crate 只来自受信任来源:

cargo deny check

整体构建

仓库根目录的 Makefile 提供了make一站式构建入口(all目标 =neon+postgres-install+neon-pg-ext),默认BUILD_TYPE=debug,可用BUILD_TYPE=release切换;PostgreSQL 各版本扩展通过neon-pg-ext-<version>目标编译安装。

使用 Python:测试环境与强制检查

由于 Debian/Ubuntu 自带的 Python 包普遍过旧,官方不建议手动安装依赖,而是用一个统一的虚拟环境描述在 pyproject.toml 中(poetry 管理,package-mode = false)。

前置条件

  • 安装Python 3.11(最低支持版本)或更高版本。poetry 配置同样兼容更新版本;如果遇到问题,可单独安装 Python 3.11:
    # Ubuntu 示例 sudo add-apt-repository ppa:deadsnakes/ppa sudo apt update sudo apt install python3.11
  • 安装poetry(对精确版本不敏感,按官方文档安装即可)。
  • 通过./scripts/pysync安装依赖(注意 CI 使用特定 Python 版本,本地版本不同可能导致部分 lint 工具结果与 CI 有差异;可用poetry env use /path/to/python指定解释器,例如poetry env use python3.11)。

激活虚拟环境:

poetry shell

或单次运行:

poetry run pytest

强制检查:ruff + mypy

项目强制用ruff统一格式、用mypy保证类型标注。在仓库根目录(紧挨pyproject.toml)运行:

poetry run ruff format . # 格式化所有代码 poetry run ruff check . # Python 语法检查 poetry run mypy . # 确保没有类型错误

警告:不要从仓库根目录以外的目录运行mypy,否则它找不到配置文件(pyproject.toml 中配置了mypy_pathstrict = true,并针对_jsonnetasyncpgpg8000等模块做了ignore_missing_imports覆盖)。另外可考虑运行pycodestyle(或你喜欢的 linter)修复潜在缺陷,并补充类型标注以避免Any

变更 Python 依赖

新增或修改包时,可用poetry addpoetry update,或直接编辑pyproject.toml;后者记得运行poetry lock更新锁文件。更多细节参考 poetry 官方文档。

配置 IDE:以 CLion 为例

Neon 由三种语言、三种项目模型构成:根 Cargo.toml 下的多个 Rust crate、test_runner目录下的 Python 集成测试、以及基于 Makefile 用 C 构建的 Postgres 扩展(vendor/postgres*pgxn)。这里以 CLion 为例说明配置方法。

使用 Rust 插件

CLion 配合 Rust 插件打开 Neon 仓库即可同时识别 Rust 与 Python 工程(官方未尝试配置调试器)。

为 C 代码生成编译数据库

C 代码通过 Make(而非 CMake)构建,需借助compilation database(一个列出所有 C 源文件及编译参数的 JSON 文件)让 CLion 理解工程:

  1. 克隆 Neon 仓库并安装全部依赖(含 Python),先不要用 CLion 打开;
  2. 在仓库根目录执行:
    # 安装 compiledb 工具,解析 make 输出并生成编译数据库 poetry add -D compiledb # 清理构建树以便全量重建(Makefile 与 --dry-run/--assume-new 兼容不佳, # 生成编译数据库目前只能完整重编译一次) make distclean # 全量重建 Postgres 部分并把编译命令存入编译数据库(-j 参数可按需调整) make -j$(nproc) --print-directory postgres-v15 neon-pg-ext-v15 | poetry run compiledb --verbose --no-build # 卸载工具 poetry remove -D compiledb # 确保 compile_commands.json 不被提交 echo /compile_commands.json >>.git/info/exclude
  3. 在 CLion 中"Open File or Project",选择生成的compile_commands.json作为项目打开(编译数据库不能加入已有 CLion 工程,且不要打开目录,要打开该文件);
  4. 项目开始索引 C 源码与 C 标准库后,可能需要为编译数据库配置 C 编译器;
  5. 在同一工程内用编辑器打开根Cargo.toml,CLion 会提示并开始索引 Rust 代码;
  6. 这样你就有了一个同时认识 C 文件、Rust 文件(并自动识别 Python 文件)的 CLion 工程;
  7. 在 CLion 设置中配置缩进:Editor > Code Style > C/C++,顶部 scheme 选 "Project",在 "Tabs and Indents" 勾选 "Use tab character",Tab size 设为 4。

你还可以开启 Cargo Clippy 诊断、用 Rustfmt 替代内置格式化器。当 C 文件布局变化时,只需重新生成编译数据库,无需重建 CLion 工程。

已知问题

  • CLion 中测试结果(Rust 单元测试与 Python 集成测试)可读性较差,建议改用命令行运行;
  • CLion 不支持非本地 Python 解释器(不同于 PyCharm),例如 WSL 环境下 CLion 看不到poetry与已装依赖,Python 支持受限;
  • CLion 中的 Cargo Clippy 诊断可能占用较多资源;
  • poetry add -D即使随后poetry remove -D也会大幅改动poetry.lock,可用git checkout poetry.lock配合./scripts/pysync还原。

结语:一张地图,三条主线

回顾整棵源码树,可以归纳出三条开发主线:

  1. 存储链路storage_broker(信息分发)→storage_controller(集群编排)→pageserver(数据落地与页面服务)→safekeeper(WAL 暂存与共识)→libs/walproposerlibs/wal_decoderlibs/remote_storage(底层支撑);
  2. 计算链路pgxn/neon(存储管理器扩展)→pgxn/neon_walredo(重放进程)→compute_tools(计算节点管理)→proxy(连接路由与认证);
  3. 工程支撑control_plane(本地编排)、test_runner(pytest 集成测试)、workspace_hack+libs/(依赖固定与共享库)、docs/(架构文档)。

无论你是要定位某个 WAL 记录的处理路径、为扩展新增一个 SQL 函数,还是要搭建本地测试环境,都可以从这张目录地图出发,顺着对应的 crate 与文档继续深入。而本仓库各子目录间的协作关系,也可以进一步在 docs/pageserver-services.md、docs/walservice.md 与 docs/storage_broker.md 中获得更完整的架构视角。

【免费下载链接】neonNeon: Serverless Postgres. We separated storage and compute to offer autoscaling, code-like database branching, and scale to zero.项目地址: https://gitcode.com/GitHub_Trending/ne/neon

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询