PGXN v2/体系结构
简介
该文档概述了构建扩展分发、发现和打包工具及服务的项目,以支持 PostgreSQL 扩展生态系统的增长、可访问性和实用性。以整个 PostgreSQL 社区为受众,它定义了要提供的服务和运行服务的体系结构,以及指导项目规划和决策的战略愿景。
为了进行战略性思考和务实规划,该文档描述了前者以实现后者。因此,它必然是高层面的;详情、范围和规划将在更注重项目的文档中展现。
请记住,该文档概述了一项宏伟的长期战略。如果你认为这里的内容太多,我们对系统进行了过度思考和过度设计,请放心,项目执行将从根本上逐步进行且务实。该文档是该项目的指导原则,并且会随着开发的进行和新问题的出现而发生变化。
管理该项目的整体理念是
- 独立服务的分散式、松散配对架构
- 元数据优先,以增强新颖、无法预期的服务
- 广泛可用,让所有人都可以构建
- 全面编制索引,成为面向所有公开可用的扩展的首选
- 优先设计,但灵活地定期调整
- 在可行情况下并行构建
- 赋能解耦或轻微耦合交互,以实现高度并行开发
- 可用性和实用性:对于扩展开发人员、服务设计师和扩展用户而言,使用服务和工具应尽可能简单明了且有用
当前架构
如今的扩展生态系统包含各种最多松散连接的服务,它们各自旨在解决特定问题。其中包括
- PGXN,旨在成为查找所有扩展并下载其源代码的综合源。不幸的是,它可能只编制了三分之一的已知扩展的索引,其中许多已多年未更新。
- PostgreSQL 社区包管理注册表,apt.postgresql.org 和 yum.postgresql.org。每个都包含一部分扩展,这些扩展由社区志愿者手动审查生成软件包规格文件,这些文件从包括 PGXN 和 GitHub 等源代码仓库在内的各种源下载源代码
- dbdev,一个面向受信任语言扩展(或 TLE)的开源注册表,开发人员可以 通过 CLI 进行发布。此注册表未与任何其他服务有任何已知的连接,虽然公共仓库可能会使用发布管道来发布 TLE。
- 其他各种二进制包管理程序,特别是 trunk 和 pgxman 项目。和社区注册表一样,这些包管理程序包含一部分经过审查的可用扩展,当前由人工维护,并为少量操作系统、架构和 PostgreSQL 版本提供二进制文件。trunk 产品路线图反映了其志向,即在更广泛的平台集合上成为所有扩展的默认二进制包源。为此,它已实施了一项概念验证,以自动打包 PGXN 上的新扩展版本。
这些系统产生时几乎相互没有参照,也没有考虑扩展生态系统的全面视图或对它们在该系统中的角色进行系统性方法。每个都简洁地解决了它着手解决的问题,而功能上有一些重叠,对于元数据管理,尤其采用类似但不兼容的方法。
挑战
由于此类善意努力的分离和缺乏协调,Postgres 扩展生态系统仍然捉襟见肘,并面临诸多长期发展挑战。这些挑战包括
- 扩展难以查找和发现。没有一个全面且权威的归属所有权供人们查找并了解所有可公开使用的扩展。
- 扩展的文档不足且难以理解。除了少数例外,大多数扩展的说明文档都只有简单却充满善意的 README 摘要,没有参考文档或教程。
- 扩展配置和安装颇具挑战性。绝大多数扩展使用 PGXS、make、configure 或 pgrx 等工具,而这些工具无一例外都需要类似编译器的内部工具。大多数用户并不需要或想要编译器,他们只需要一个简单的命令来安装所需的二进制文件即可。但遗憾的是,二进制注册表只提供了极少数平台的扩展集合。
- 扩展项目的成熟度可能难以判断。在没有一个具有统一、可比统计数据、文档和元数据的中央存储库的情况下,有兴趣的用户必须找到扩展源(再次难以查找!)以及研究启发式方法,例如存储库星形标、提交历史记录和文档质量,而这些指标在竞争项目之间可能存在很大的差异。
- 开发者工具通常神秘、难以理解且文档不足。没有一项资源可以帮助初露锋芒的扩展开发者学习此项手艺,自动化他们的流程以及为更广泛的社区做出贡献。
未来架构
为了应对上述许多挑战,本项目将在明年建立一个由交互服务、客户端和工具组成的分布式架构,以促进未来扩展生态系统的发展和可访问性。
该架构由六个核心系统组成,每个系统都是一个“拥有”明确定义的能力单元。这些逻辑模型定义了系统之间的交互指南,而不一定是物理实体或网络图。本文档将在下面介绍每个系统,定义其与其他系统协作的背景,以及预计构成该服务的组件。
根注册表
根本服务构成了根注册表,该注册表的目的是成为公开可用扩展的全面记录系统。开发者会将扩展源代码发布到注册表,通过其 API(使用CLI)或Web UX管理所有权和权限。
API 将提供注册表的所有功能,使用户能够搜索、阅读文档、下载和安装扩展、检查其他注册表对象(用户、分类等)的数据,以及查看或点击以阅读其他统计信息和报告。
功能
- 存储层
- 根镜像
- 数据库
- 标识与身份验证 API
- 注册
- 身份验证
- 账户管理
- 用户管理
- API 身份验证
- 授权(访问控制)
- 发布 API
- 发布
- 验证
- 所有权/权限
- 索引服务
- 文档生成
- 搜索索引
- 其他索引(例如 Atom 信息流)
- 信息 API
- 元数据
- 下载
- 搜索
- 文档
- 个人资料(扩展、用户、分类)
- 统计和报告(通过交互)
背景知识
根注册表提供核心功能,以支持下面定义的服务。简而言之
- Web UX服务通过根注册表提供一个人类可访问的交互层
- 客户端依赖根注册表下载扩展和元数据,包括二进制包信息,并且可以用来发布新扩展
- 打包服务依赖根注册表获取源代码,以及依赖交互来获取新版本的通知
- 交互服务通过webhook向已注册的下游服务发送新版本通知,并提供用于提交包链接和统计和报告的 API。
- 统计和报告服务提供增强扩展价值的其他服务,可以从根注册表下载源和元数据,并通过交互返回数据,以便在 Web UX中显示。
Web UX
该 Web 服务为用户提供 UX,以便用户可以使用所有根注册表 API。它作为一个设计精美的交互层,覆盖在提供所有功能的根注册表之上。其客户端是互联网上的基于 Web 的设备。
随着交互向根注册表添加其他 API、数据和功能,Web UX 将更新为显示这些功能。
Web UX 服务并非唯一的 UX 服务。作为覆盖根注册表 API 的纯显示层,它设置了用户交互的标准,但其他用户可以构建自己的 UX 客户端,例如本机桌面或移动应用程序。
功能
- 搜索扩展和其他实体
- 浏览分类
- 阅读文档
- 浏览源代码
- 下载源代码
- 浏览和查看用户个人资料
- 列出最新版本
- 链接到下游二进制打包服务
- 显示第三方元数据(统计数据、徽章、链接等)
- 用户注册和认证
- 扩展管理(权限、所有权)
- API 令牌管理(针对用户)和管理(针对监管)
- 用户管理和其他管理任务
背景知识
Web UX 服务依赖于根注册表的 API 来提供所有功能(图 3)。虽然网站应当设计美观、引人入胜、内容丰富且用起来有趣,但它不应提供任何自身的业务逻辑。
PGXN 为根注册表提供了大量灵感。不妨将其看作将pgxn.org 和 manager.pgxn.org 合并到单个站点中。PGXN 本身将要么演变为承担此处定义的根注册表的责任,要么修改为与根注册表无缝对接,以使 PGXN 上的新版本也会进入根注册表。
交互
根注册表 会向事件流服务发布事件,该服务会将这些事件发送到已注册和已批准的客户端服务的网络挂钩,特别是打包和统计和报告。与此同时,可写 API 会允许可信、经过身份验证的客户端提交其他元数据、打包信息、报告结果和统计数据到注册表。
交互服务的设计需要详细的治理规范才能确定哪些服务是受信任的、它们必须满足哪些标准以及行为准则和审查节奏以确定是否应撤销访问权限。从技术上讲,它还需要一个健壮且可审查的身份验证和授权系统来确保访问控制得到强制执行,并且易于管理,也就是授予或撤消访问权限。
功能
- 事件流
- 社交发布
- Webhook
- 写 API
- 统计信息(下载、存储库统计信息)
- 报告(测试结果、安装结果、安全扫描)
- 打包
背景知识
交互服务充当根注册表的扩展,管理事件流和写入 API,为受信任的打包和统计和报告服务提供服务。它使用该数据来更新根注册表管理和发布的适当扩展元数据,以通过Web UX增强和丰富扩展数据及其显示,以便更好地通知和取悦用户。
客户端
客户端是该架构的关键组件,因为它旨在提供能力来授权
- 希望找到、安装并报告扩展及其在系统中的依赖项的用户
- 需要搭建新项目、管理扩展元数据、在多个平台和 Postgres 版本上构建源代码并运行测试以及发布新版本的开发人员
- 可能依赖于其广泛的构建管道和依赖项管理功能来简化打包自动化的打包人员
- CI/CD 自动化
目标是构建一款健壮、直观的客户端,可以轻松安装在各种操作系统和平台(例如单一的交叉编译的 Go 或 Rust 二进制文件)上,并具有一个架构来识别和使用各种配置矩阵,包括
- 操作系统:Linux、macOS、*BSD、Windows 等
- 架构:amd64、arm64、i386 等
- 处理能力:CPU、GPU、avx512 等
- PostgreSQL 版本:9.1 - 17
- 打包人员:apt.postgresql.org、yum.postgresql.org、trunk、dbdev、pgxman 等
- 构建管道:PGXS、pgrx、configure、make、cmake 等等。
- 扩展类型:SQL 扩展、后台工作进程、应用程序、可加载模块 等。
目标是让客户端成为在大多数平台上使用大多数 PostgreSQL 发行版开发和安装扩展的默认选择。
功能
- 用户 SDK
- 列出扩展
- 搜索扩展
- 确定环境(Postgres 版本、操作系统、架构)
- 获取适合配置的适当二进制包
- 解析和安装所有扩展、系统和库依赖项
- 安装(或重新安装)软件包
- 为所有受支持管道从源代码构建
- 验证某个扩展是否已安装
- 确认安装成功
- 在一个或多个数据库中使用
CREATE EXTENSION
等语句。 - 同时使用私有注册表和根注册表
- 报告已安装扩展及它们的状况(已用/未使用、已过期)
- 开发者 SDK
- 初始化项目
- 管理元数据
- 为所有受支持管道构建和安装
- 在不同的 Postgres 版本上运行测试
- 捆绑和发布
- 发布到私有注册表
- SDK 周围的 CLI 封装器
- 执行 CI/CD 任务
- 尽可能支持尽可能多的操作系统
- 便于分发(每个操作系统/架构对应一个二进制文件)
背景知识
如图 图 2 和 图 4 所示,客户端与 根注册表、打包服务以及潜在的系统和下游打包程序进行交互。
客户端依赖根注册表的 API 来发布扩展、搜索扩展以及获取扩展的元数据。基于此元数据,它了解如何执行以下操作:
- 下载、构建和安装扩展及其依赖项
- 确定 打包 服务是否提供了适当的二进制文件并安装它
- 评估可用的下游打包程序的二进制软件包并选择最适合安装的软件包
这就是客户端深入了解元数据非常关键的原因,客户端可以令开发人员对元数据管理尽可能简单,并代表用户做出知情且(容易覆盖)的决策。
这些元数据类别的每一个都需要大量设计和开发。对于源构建,客户端必须识别并理解如何使用各种构建管道和依赖关系管理系统。它还需要修改每个管道配置的能力,以便对扩展安装进行更精细的控制,例如防止某些文件(例如文档)被安装,以及设置安装位置(PGDATA 和 pg_config 报告的各种目录:bindir
、docdir
、libdir
等),正如特别需要从 Packaging 服务安装二进制文件时的那样。
在使用下游打包工具时,它需要了解它所管理的系统,以便它能够安装最佳软件包及其所有依赖关系。可能某种配置可以将其锁定到特定打包工具,但同时对于某人来说它需要尽可能简单才能轻松找到、下载并尝试一个扩展。
有趣的想法
是否可以使用 CLI SDK 作为 Postgres 扩展,这样人们就可以做客户端能做的一切事情---或至少安装二进制包---但是通过 SQL 函数调用。请参阅 pginstall,了解 POC。
打包
打包服务侦听 webhook 调用或源更新,以便下载、构建和打包针对各种平台的新版本。理想情况下,它将通过有效使用 VM 或容器支持各种操作系统、操作系统版本、Postgres 版本和架构。它的软件包只会包含要安装的扩展文件,并且客户端会知道如何将它们安装到给定的集群中。
生成的 tarball(或 zip 文件;请参阅 二进制分发格式 以获取灵感)存储库将用作客户端的默认安装源。然而,其他打包器可以依赖于打包服务或根注册表来构建它们的包。
这些下游打包器可以通过 交互 收到有关新源发行版或二进制构建的通知,受信任的服务还可以提交打包链接,以及定期下载统计数据(如果可用)。
此架构旨在使任意数量的实体能够创建并维护二进制扩展打包存储库。我们预计没有单一服务能够满足所有可用的操作系统、平台、硬件架构或 PostgreSQL 版本的需求,尽管打包服务本身旨在涵盖 90% 的现代用例。
功能
- 管理构建节点的架构
- 侦听新版本的 Webhook
- 排队构建 Linux、macOS 和 Windows 的节点(虚拟机或容器),2-3 个最近的操作系统版本和 64 位架构
- 支持针对多个 PostgreSQL 版本进行构建,至少支持核心仍支持的那些版本
- 用于下载源代码、构建二进制文件、汇编元数据(包括特定于系统的包和库依赖项)并将所有这些捆绑到一个 zip 文件中的客户端
- 针对 zip 文件进行公钥签名
- 将结果发布到 交互,以便可以在 根注册表 中列出二进制支持
- 用于下载的 zip 文件存储库
- 镜像(rsync?)
- 第三方用于构建客户端可以透明地使用的自己的打包注册表的协议
- 供下游打包器使用的二进制构建事件
我们预计整体架构将允许任何人创建自己的注册表,并自动从打包服务创建的二进制文件或根注册表上发布的源代码构建包。通过这种方式,扩展的好处可以扩展到比其他可能的方式更多得多的操作系统、平台和架构。
背景知识
打包服务将通过 交互 服务的 Webhook 回调收到有关新扩展发行版的通知。
在发布事件中,打包服务将从根注册表下载源代码,以便在其各个构建节点上进行构建。这些节点还将依靠客户端 SDK 对构建管道的大力支持来构建扩展。一旦构建了扩展,它将收集相关文件(控制文件、SQL 脚本、动态库文件和文档)以及描述文件和二进制配置(操作系统版本、PostgreSQL 版本、架构、配置要求(例如,shared_preload_libraries
)、系统和库依赖项等)的清单打包到一个 zip 存档中。
对于每个由此创建的二进制包,它会发布一个事件给 Interactions 服务。下游打包器(例如 yum、apt、pgxman、Homebrew、Chocolatey 等)可以订阅这些事件以使用打包服务创建的二进制文件来构建它们自己的包。或者它们可以订阅新版本事件并从源代码进行构建。
无论哪种方式,使用扩展的元数据,它们都可以自动构建并注册二进制包。一旦包发布,受信任的打包客户端可以将指向它们的链接发回 Interactions 服务,然后服务将更新元数据,以便链接显示在扩展的 Web UX 页面上。
客户端还受益于这些链接,因为它可以在给定系统上选择要安装的最佳可用包。换句话说,如果要求客户端将扩展安装到基于社区的 Apt Postgres 集群中,它可以选择该扩展的社区 Apt 包。对于具有不确定源的集群(例如,从源代码构建),它将默认从打包服务安装二进制文件,或者如果用户愿意,则从根注册表下载的源代码中安装。
受信任的打包器还可以定期向 Interactions 服务发布统计信息更新,包括下载次数、安装成功和失败等,该服务会在扩展元数据中汇总这些统计信息,以便在网站上或由客户端显示。
统计信息和报告
统计和报告服务对扩展执行操作,然后报告结果。受信任的实例可以通过交互服务提交统计、链接、徽章和指向 Interactions 的链接,以便通过 Web UX 和其他客户端显示。
统计和报告实际上是一个超级开放的类别,只意味着“使用扩展执行操作的服务”。这一操作可能是未指定的。这里有一些想法
- 通过发布到社交媒体网站、电子邮件列表、Slack 频道等来宣布新版本的服务。
- 定期报告扩展的存储库统计信息的服务,例如星数、问题数量、请求提取数量、贡献者数量等。在 Web UX 中更新这些统计信息以显示有助于集中扩展质量的评估。
- 一项服务,在每次发行后下载扩展,对它们在各种操作系统和 Postgres 版本上进行简单测试,并建立一个矩阵,在网上报告结果。它可能会提交一些简单的统计数据(通过/失败/跳过计数),徽章指示总体结果,并链接回矩阵页面。
- 一项简单测试服务的变体,测试从早期版本升级后报告成功和失败的统计数据以及制作变更 diff。
- 一项允许用户对扩展评分或撰写评论的服务。它可能会提交链接到讨论以及一些统计数据,比如平均评分或评论计数。这可以帮助用户评估扩展的质量。
- 一项服务,在每次发行后下载扩展并扫描它们的安全漏洞。可能提交一些基本统计数据(建议数量、质量徽章)以及链接到更深入的评估。它甚至可能是一项付费服务,收取客户费以获取更多信息,或提供仅包含低漏洞扩展的私有存储库。
- 一项服务,根据其自己的优先级和系统对扩展进行整理和分类。它可能会回报主要的分类术语,或者对用户分类进行社交向上/向下投票。
针对本项目的目的,我们提议实施其中前两个示例:一项社交媒体公告服务和一项源仓库统计数据聚合器。这两项服务均提供高水平的质量信号,这对于人们了解新版本、评估开发人员的活动以及验证模型并为其他人树立示例至关重要。