RFC-0182:废弃了 config-data

RFC-0182:弃用 config-data
状态已接受
区域
  • 组件框架
说明

打算弃用在代码库之间提供/使用组件配置文件的旧版机制

问题
Gerrit 更改
作者
审核人
提交日期(年-月-日)2022-06-30
审核日期(年-月-日)2022-08-15

摘要

此 RFC 建议:

  • [config-data] 机制声明为已弃用。
  • 为现有使用情形建立许可名单。
  • 随着时间的推移,将 config-data 的现有用法替换为其他更好的解决方案。
  • 最终从 Fuchsia 中移除对 config-data 的支持。

设计初衷

此 RFC 的直接目标是就为现有 config-data 用法创建许可名单达成大致共识,并倾向于不扩大该许可名单。为提供更多背景信息,并应各种利益相关方的要求,我们还提供了与此直接目标无关的其他信息。

[config-data] 是一种用于配置文件的机制,通过在运行时使某些文件在封装组件的命名空间中可用,来调节封装组件的行为。

config-data 通过对目标组件的软件包名称使用未强制执行的合约或惯例来创建“远距离的诡异动作”。这是有问题的,因为软件包名称无法作为稳定的标识符,成为 Fuchsia SDK 表面的一部分,随 SDK 进行版本控制,并随时间推移而发展(例如通过声明支持窗口和允许软过渡)。经验表明,基于软件包名称的合约会产生脆弱的运行时假设,并且维护成本很高。

此外,由于 config-data 将开发者软件包中的内容与包含配置文件的基本软件包中的内容混合在一起,这会造成令人困惑的开发者体验,即开发者推送了软件包的新修订版本,但在运行时看到的是旧的配置文件。通常,开发者会问,为什么他们推送了软件包的更新版本,但在 /config/data 下看到的是过时的文件,而没有意识到这些文件来自不同的软件包。向开发者解释此行为需要向他们展示“基本软件包”等平台实现细节,这表明抽象失败,是不可取的。更不用说这种反复出现的工作流程不一致性会导致效率下降。

config-data 在解决以下问题时非常有用:产品组装过程中不同阶段的参与者需要影响超出其直接控制范围的组件。使用 config-data,源自一个位置(代码库、构建系统等)的配置值可用于调节源自其他位置的组件的行为。

在某些情况下,组件和配置具有相同的来源,但用户仍然倾向于使用 config-data 作为集成点。这样,用户就可以生成一个软件包,并向该软件包中包含的组件旁加载不同的配置值。当生成多个软件包的成本很高时,此功能非常有用,例如,如果每个软件包变体都需要单独上传到后续集成点。

如今,config-data 有多种替代方案。这些方法包括:基于目录功能结构化配置来路由配置目录的其他方法;通过协议功能提供配置;以及将配置文件与使用这些配置文件的组件打包在一起。

虽然弃用 config-data 的现有用法和该功能本身并非当务之急,但我们应引导新用法采用现代解决方案,并促使现有用法的所有者迁移到现代替代方案。

在这种情况下,最佳做法是为 config_data() GN 规则建立许可名单,并使用现有用量对其进行初始化。随着时间的推移,预计许可名单中的内容会逐渐减少,但如果无法确定现代替代方案是否适用,则可以将新用法添加到许可名单中。当允许新的用法时,应预先说明更改的理由,以减少代码审核的反复。

利益相关方

  • Component Framework 团队:创建了 config-data 及其当前替代方案。
  • Build 团队:config-data 构建时逻辑的维护者。
  • 软件组装团队:config-data 组装时逻辑的维护者。
  • config-data 的当前用户,涵盖多个团队。

辅导员

  • hjfreyer@google.com

审核者

  • aaronwood@google.com
  • adamperry@google.com
  • awolter@google.com
  • ddorwin@google.com
  • fmil@google.com
  • geb@google.com
  • jsankey@google.com
  • kpozin@google.com
  • wez@google.com
  • yaar@google.com
  • ypomortsev@google.com

共同化

此 RFC 的草稿在发布之前已由组件框架和软件组装技术主管审核。

背景

config-data 的运作方式

在旧版 appmgr(又称 CFv1)中,config-data 是通过将启动的组件的软件包名称与 config-data 基础软件包中的子目录进行匹配来实现的。如果找到匹配项,则在启动的组件的命名空间中,通过路径 /config/data 提供匹配的子目录。

定义 config-data 时,需要指定要提供的文件、这些文件在组件的传入命名空间中应提供的路径(按照惯例,位于 /config/data 下)以及一个或多个组件的软件包名称,这些组件应在这些路径中提供这些文件。

例如,组件可能会请求使用如下所示的配置文件:

{
    use: [
        {
            directory: "config-data",
            rights: [ "r*" ],
            path: "/config/data",
        },
    ],
}

这表示组件要求嵌入者提供名为“config-data”的只读目录功能,该功能将由框架在 /config/data 处呈现,以允许依赖于 /config/data 的现有代码在不修改的情况下正常运行。

父组件或 realm 可能具有以下声明:

{
    children: [
        {
            name: "font-provider",
            url: "fuchsia-pkg://fuchsia.com/fonts#meta/font-provider.cm",
        },
    ],
    offer: [
        {
            directory: "config-data",
            from: "parent",
            to: [ "#font-provider" ],
            subdir: "fonts",
        },
    ],
}

此方法接受一个包含多个子目录的 config-data(来自父目录),并将包含字体提供程序配置数据的 example 子目录路由到相应组件。

config-data 的内容可能来自如下构建定义:


import("//build/config.gni")

config_data("example_config_data") {
  for_pkg = "example"
  sources = [
    "file1.dat",
    "file2.dat",
    ...
  ]
  outputs = [ "{{source_file_part}}" ]
}

上述目标及类似的其他目标由 build 系统收集,以形成名为 config-data 的软件包的内容。然后,专用路由规则会将 config-data 软件包的所有内容(按上述 for_pkg 参数所示整理到子目录中)路由到核心 realm 和其他位置,这些内容会进一步配置为分发到使用它们的各种组件。

config-data 目前的使用方式

config-data 有许多使用场景。以下是一些说明性示例:

  • ICU 数据和 tzdata:ICU 库的数据,特别是时区数据(“tzdata”),在运行时以 config-data 的形式提供。在 Fuchsia 平台来源中为这些数据文件定义单一可信来源,并向来自各种来源(例如 Chromium、Flutter、内部 Google 代码库等)的组件提供这些文件,以确保仅使用这些文件的一个修订版本。这样可以实现一致性(例如,所有组件都同意使用单个 tzdata,无论其来源如何)和效率(所有组件共享相同的 ICU blob,无论它们是在何时何地构建的)。
  • buildinfohwinfo 组件的值以 config-data 形式提供。这些组件基于平台源代码构建,但可能需要由产品进行配置。目前,config-data 用作此配置机制。
  • 在平台来源中定义的“设置”界面组件可以配置为在公开不同硬件切换开关的不同设备上以不同方式运行。例如,SetUI 在 Astro 设备上的行为与在 Sherlock 设备上的行为不同,目前由 config-data 控制。
  • 平台字体提供程序组件可配置为提供特定于产品的字体。字体文件和描述其属性的清单以 config-data 的形式提供,并添加到树外产品程序集中。

设计与实现

将建立 build-time 回归停止机制,以防止在未经明确批准的情况下使用 config-data。系统将提交现有用法的许可名单,并且此许可名单的更改将受 OWNERS 文件的控制。所有者将从组件框架团队中分配,以表示 fuchsia.git,并从使用 config-data 的 petal 中分配,以表示其使用情况。代表将负责管理各自的许可名单条目,例如协助进行重构或有针对性的清理。

回归停止的实现方式并不重要。一种常见且可能的实现策略是更改 config-data GN 模板,以添加对具有一组可见性列表的目标的依赖项。值得注意的是,这仅涵盖了树内使用情况,但限制在树外产品组装中对 config-data 的新使用也很重要。您也可以与 PDK 团队协调,在此处开发适当的机制。

config-data 的替代方案进行深入探讨不在本 RFC 的讨论范围内。在参考这些替代方案时,请查看上面链接的文档。

为组件提供配置的最佳实践,或提供从 config-data 迁移的指南,不在本 RFC 的范围内。我们正在努力制作此类文档,并且会单独发布,不会包含在此 RFC 中。

性能

config-data 软件包的一个特殊且有趣的方面是,所有文件都打包在路径 meta/ 下。这意味着文件已归档到 meta.far 文件中。当存储在底层 blobfs 文件系统中时,磁盘上的文件大小会向上舍入到块大小(通常为 8KiB)。通过将配置文件一起归档,可以消除向上舍入带来的额外开销。这一点很重要,因为配置文件通常数量众多且体积较小,因此总开销实际上可能大于这些文件的压缩大小之和。

使用替代解决方案时,如果存储空间很重要,则应使用相同的技术或等效技术,以确保存储效率相当。

工效学设计

config-data 的替代方案具有更好的人体工程学设计,最重要的是,它们不依赖于基于软件包名称和“远距离操作”的脆弱合同。

向后兼容性

config-data 迁移有时需要以软过渡的方式进行。在过渡期间,使用配置数据的组件必须能够接受两种形式的输入(config-data 和所选替代方案)。

安全注意事项

此 RFC 并未引入任何新的配置机制,我们用作 config-data 替代方案的所有机制都已存在于系统中,并且已经过各自的安全审核。组件作者在设计或更改安全相关功能的配置时,应咨询安全团队。

隐私注意事项

此 RFC 未引入任何新的配置机制,我们用作 config-data 替代方案的所有机制都已存在于系统中,并且已通过各自的隐私权审核。组件作者在设计或更改隐私敏感型功能的配置时,应咨询隐私权方面的意见。

测试

config-data 提出的替代方案都有成熟的测试最佳实践。如需了解测试信息,请参阅特定功能的文档。例如,请参阅有关使用 Realm Builder 测试结构化配置的指南。替换正在测试的结构化配置值非常简单,只需执行以下操作:

realm_builder.SetConfigValue(child_name, key, value_for_test);

当我们需要以文件形式向受测组件(例如在集成测试中)提供配置数据时,可以将这些文件与测试一起打包,然后从测试组件(位于测试 realm 根目录)路由到受测组件,作为数据目录。例如:

{
    ....
    capabilities: [
        {
            directory: "test_config",
            rights: [ "r*" ],
            path: "/test_config",
        },
    ],
    children: [
        {
            name: "component_under_test",
            ...
        },
    ],
    offer: [
        {
            directory: "test_config",
            from: "self",
            as: "config",
        },
    ],
}

文档

为了支持从 config-data 迁移,我们将提供迁移指南。该迁移指南将帮助开发者为其使用场景选择最佳替代方案,并引导他们参阅其他文档。

有关人员配置和客户流失的说明

接受此 RFC 不会要求 config-data 的现有用户迁移到现代替代方案。如果已下达迁移指令,则应组建核心迁移团队,负责执行大部分工作。作者建议,在 CFv2 迁移完成之前,不应开始此类工作,但我们应尽快完成并提交回归停止。

在有专门的人员负责迁移之前,对许可名单的更新(例如支持重构)应在一个工作日内完成审核和批准。

缺点、替代方案和未知因素

结构化配置是一种仍在不断发展的新机制。例如,表达配置所需的一些功能(例如额外的数据类型)尚未实现。

功能路由目前不受平台版本控制的约束。我们计划构建对 ABI 修订版上调节功能路由的支持,但此机制尚未设计。