PGXN v2/架构
简介
本文档概述了构建扩展分发、发现和打包工具和服务的项目,以推动 Postgres 扩展生态系统的增长、可访问性和效用。该项目以整个 Postgres 社区为目标受众,定义了要提供的服务和运行它们的架构,以及指导项目规划和决策的战略愿景。
为了战略性地思考和务实地规划,本文档描述了前者以实现后者。因此,它必然是高级别的;详细信息、范围和规划将在更专注于项目的文档中呈现。
请记住,本文档概述了一个雄心勃勃的长期战略。如果您认为这里的内容太多,我们过度思考和过度设计了系统,请放心,项目执行将从根本上是渐进的和务实的。本文档是项目的指导灯塔,并且会随着开发的进行和新问题的出现而发生变化。
指导该项目的总体理念是
- 独立服务的分布式、松散配对架构
- 元数据优先,以赋能新颖、不可预知服务
- 广泛可用性,供任何人构建
- 全面索引,成为所有公开可用扩展的首选
- 先设计,但定期敏捷调整
- 在可行的情况下并行构建
- 赋能解耦或轻耦合交互,实现高度并行开发
- 可用性和易用性:使用服务和工具应该尽可能直观且明显地对扩展开发人员、服务设计师和扩展用户有用
当前架构
当今的扩展生态系统由各种最多只能算是松散连接的服务组成,这些服务都旨在解决特定问题。这些包括
- PGXN,旨在成为查找所有扩展并下载其源代码的全面来源。不幸的是,它索引了大约三分之一的已知扩展,其中许多已经多年没有更新了。
- PostgreSQL 社区打包注册表,apt.postgresql.org 和 yum.postgresql.org。每个注册表都包含一组扩展,由社区志愿者手动维护,他们手动编写打包规范文件,从各种来源下载源代码,包括 PGXN 和源代码存储库,例如 GitHub。
- dbdev,一个面向受信任语言扩展的开源注册表,或 TLE,开发人员 通过 CLI 发布。该注册表没有已知与任何其他服务的连接,尽管公共存储库可能会使用发布管道来发布 TLE。
- 其他各种二进制打包程序,尤其是 trunk 和 pgxman 项目。与社区注册表一样,这些打包程序包含一小部分可用扩展,目前手动维护,并为一小部分操作系统、体系结构和 Postgres 版本提供二进制文件。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 服务为用户使用所有根注册表 API 提供 UX。它充当在根注册表之上的一个设计精美的交互层,该注册表提供了所有功能。它的客户端是互联网上的基于 Web 的设备。
当 交互 向根注册表添加其他 API、数据和功能时,Web UX 将更新以显示它们。
Web UX 服务不必是唯一的 UX 服务。作为根注册表 API 之上的一个纯显示层,它为用户交互设定了标准,但其他人可以构建自己的 UX 客户端,例如本机桌面应用程序或移动应用程序。
功能
- 搜索扩展和其他实体
- 浏览分类
- 阅读文档
- 浏览源代码
- 下载源代码
- 浏览和查看用户配置文件
- 列出最近的版本
- 链接到下游二进制打包服务
- 显示第三方元数据(统计数据、徽章、链接等)
- 用户注册和身份验证
- 扩展管理(权限、所有权)
- API 令牌管理(用于用户)和管理(用于监督)
- 用户管理和其他管理任务
上下文
Web UX 服务依赖于根注册表的 API 来提供所有功能(图 3)。尽管网站的设计应该精美、引人入胜、信息丰富且使用起来很有趣,但它本身不应该提供任何业务逻辑。
PGXN 为根注册表提供了很多灵感。可以把它想象成将 pgxn.org 和 manager.pgxn.org 合并到一个网站中。 PGXN 本身将要么演变成这里定义的根注册表的责任,要么被修改为与根注册表无缝衔接,这样 PGXN 上的新版本也会发布到根注册表。
交互
根注册表 将事件发布到事件流服务,该服务将它们发送到 Webhook,用于已注册和批准的客户端服务,特别是 打包 和 统计数据和报告。同时,可写 API 将允许受信任的、经过身份验证的客户端向注册表提交其他元数据、打包信息、报告结果和统计数据。
交互服务的設計需要詳細的治理规范,以确定哪些服务将被信任,它们必须满足什么标准,以及行为准则和审查节奏,以确定是否应撤销访问权限。从技术上讲,它还需要一个健壮且可审计的身份验证和授权系统,以确保访问控制得到执行,并且管理起来很简单——也就是说,授予或撤销访问权限。
功能
- 事件流
- 社交发帖
- Webhook
- 写 API
- 统计数据(下载量、仓库统计数据)
- 报告(测试结果、安装结果、安全扫描)
- 打包
上下文
交互服务充当 根注册表 的扩展,管理事件流和为受信任的 打包 和 统计数据和报告 服务提供写 API。它使用这些数据来更新由根注册表管理和发布的适当扩展元数据,以增强和丰富扩展数据及其通过 Web UX 的显示,从而更好地告知和取悦用户。
客户端
客户端是架构的关键组成部分,因为它旨在提供功能来赋予
- 想要在他们的系统上查找、安装和报告扩展及其依赖项的用户
- 需要搭建新项目、管理扩展元数据、构建源代码并在多个平台和 PostgreSQL 版本上运行测试,以及发布新版本的开发人员
- 可能依赖其广泛的构建管道和依赖项管理功能来简化打包自动化的打包程序
- 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
等),这是在特别情况下安装来自 打包 服务的二进制文件所必需的。
当使用下游打包程序时,它需要了解它管理的系统,以便它可以安装最佳的包及其所有依赖项。可能某种配置可以将其锁定到特定的打包程序,但同时它也需要尽可能简单,以便用户可以轻松地查找、下载和尝试扩展。
有趣的想法
是否可以使用 CLI SDK 作为 Postgres 扩展,以便可以通过 SQL 函数调用完成客户端可以执行的所有操作——或者至少安装二进制包?有关 POC,请参阅 pginstall。
打包
打包服务监听 Webhook 调用或提要更新,以下载、构建和打包针对各种平台的新版本。理想情况下,它将通过有效地使用 VM 或容器来支持各种操作系统、操作系统版本、Postgres 版本和体系结构。它的包将只包含要安装的扩展文件,客户端将知道如何将它们安装到给定集群中。
由此产生的 tarball 库(或 zip 文件;请参阅 二进制发行版格式 以获取灵感)将用作客户端的默认安装源。但是,其他打包程序可以依赖于打包服务或根注册表来构建他们的包。
这些下游打包程序可以通过 交互 收到有关新源版本或二进制构建的通知,并且受信任的服务也会提交打包链接以及可用的定期下载统计数据。
这种架构旨在使任何数量的实体能够创建和维护二进制扩展打包存储库。我们预计,没有一项服务能够满足所有可用的操作系统、平台、硬件体系结构或 PostgreSQL 版本的需求,尽管打包服务本身旨在涵盖 90% 的现代用例。
功能
- 用于管理构建节点的架构
- Webhook 用于监听新版本
- 将构建排队到用于 Linux、macOS 和 Windows、2-3 个最近的操作系统版本以及 64 位体系结构的构建节点(VM 或容器)
- 支持针对多个版本的 Postgres 构建,至少是那些仍受核心支持的版本
- 客户端下载源代码,构建二进制文件,组装元数据(包括系统特定的包和库依赖项)并打包成一个 zip 文件。
- 对 zip 文件进行公钥签名。
- 将结果发布到 交互,以便二进制支持可以在 根注册表 中列出。
- zip 文件的下载库。
- 镜像(rsync?)。
- 用于第三方构建自己的打包注册表的协议,客户端可以透明地使用这些注册表。
- 二进制构建事件,供下游打包者使用。
我们期望整体架构允许任何人创建自己的注册表,并从打包服务创建的二进制文件或根注册表发布的源代码自动构建包。通过这种方式,扩展的好处可以扩展到比其他方式可能更广泛的操作系统、平台和架构。
上下文
打包服务将通过来自 交互 服务的 webhook 回调来收到新的扩展版本发布的通知。
在发布事件发生时,打包服务将从根注册表下载源代码,并在其每个构建节点上进行构建。这些节点还将依赖于客户端 SDK 对构建管道的广泛支持来构建扩展。构建扩展后,它将收集相关文件(控制文件、SQL 脚本、动态库文件和文档),以及描述文件和二进制配置的清单(操作系统版本、PostgreSQL 版本、架构、配置要求(例如 shared_preload_libraries
)、系统和库依赖项等)到一个 zip 归档文件中。
对于这样创建的每个二进制包,它都会向 交互 服务发布一个事件。下游打包者(例如,yum、apt、pgxman、Homebrew、Chocolatey 等)可以订阅这些事件,以从打包服务创建的二进制文件中构建自己的包。或者他们可以订阅新的版本发布事件并从源代码构建。
无论哪种方式,使用扩展的元数据,他们都可以自动构建和注册二进制包。发布包后,受信任的打包客户端可以将指向它们的链接发布回 交互 服务,然后该服务将更新元数据,以便这些链接显示在扩展的 Web 用户界面 页面上。
客户端也从这些链接中受益,因为它可以随后选择最适合在给定系统上安装的包。换句话说,如果客户端被要求将扩展安装到基于社区 Apt 的 PostgreSQL 集群中,它可以选择该扩展的社区 Apt 包。对于源代码不确定的集群(例如,从源代码构建),它将默认安装来自打包服务的二进制文件,或者如果用户想要,则从根注册表下载的源代码。
受信任的打包者还可以定期将统计数据更新(包括下载次数、安装成功和失败等)发布到 交互 服务,该服务将汇总这些统计数据,并在扩展元数据中显示在网站或客户端上。
统计数据和报告
统计数据和报告服务对扩展执行操作,然后报告结果。受信任的实例可以提交统计数据、链接、徽章和指向 交互 服务的链接,以便通过 Web 用户界面 和其他客户端显示。
统计数据和报告故意是一个超级开放的类别,仅仅意味着“对扩展执行操作的服务”。具体操作是什么,还没有指定。以下是一些想法。
- 一个通过发布到社交媒体网站、电子邮件列表、Slack 频道等来宣布新版本的服务。
- 一个定期报告扩展的存储库统计数据的服务,例如星标、问题数、拉取请求数、贡献者数量等。更新这些统计数据以在 Web 用户界面 中显示有助于集中评估扩展的质量。
- 一个为每个版本下载扩展并在各种操作系统和 PostgreSQL 版本上对其进行冒烟测试的服务,并构建一个在网络上报告结果的矩阵。它可能提交简单的统计数据(通过/失败/跳过计数)、一个指示总体结果的徽章以及指向矩阵页面的链接。
- 冒烟测试服务的变体,它测试从早期版本的升级,并报告成功和失败的统计数据,并生成更改的差异。
- 一个允许用户对扩展进行评分或撰写评论的服务。它可能提交指向讨论的链接以及一些统计数据,例如平均评分或评论数。这可以帮助用户评估扩展的质量。
- 一个为每个版本下载扩展并扫描其安全漏洞的服务。它可能提交一些基本统计数据(咨询数、质量徽章)以及指向更深入评估的链接。它甚至可以是一项付费服务,向客户收取访问更多信息的费用,或者提供仅包含低漏洞扩展的私有注册表。
- 一个根据自己的优先级和系统对扩展进行整理和分类的服务。它可能提交回主要分类术语,或者提交用户对分类的社会向上/向下投票。
在本项目的范围内,我们建议实现以下两个示例:社交媒体公告服务和源代码存储库统计数据聚合器。这两项服务都提供了高度的质量信号,这对人们了解新版本和评估开发人员活动非常重要,并且证明了模型,并为其他人树立了榜样。