跨单元格调整大小

https://blueprints.launchpad.net/nova/+spec/cross-cell-resize

扩展调整大小(冷迁移)支持到多个单元格。

问题描述

多单元格支持已添加到 Pike 版本的控制器服务(API、conductor、scheduler)。然而,服务器移动操作,例如调整大小,仅限于实例当前所在的单元格。由于部署通常按硬件类型对单元格进行分片,因此 flavor 隔离到该硬件,无法跨单元格调整大小是一个问题,当部署希望将工作负载从旧硬件(flavor)迁移到新硬件时。

用例

作为一个大型多单元格部署,按硬件代数分片单元格,我希望停用旧单元格中的旧硬件,并让新的和现有的服务器迁移到运行较新硬件和较新 flavor 的新单元格,而无需用户销毁和重新创建他们的工作负载。

作为一个用户,我希望我的服务器在迁移到另一个单元时保留它们的IP地址、卷和UUID。

提议的变更

这是一个复杂的变化,概念验证补丁 [1] 表明了这一点。因此,我将把本节分解为子节,以涵盖需要实现和原因的各个方面。

请记住,从高层来看,这主要是从一个单元格到另一个单元格的大量数据迁移。

本规范试图提供一个高级设计,基于使用基于shelve的方法的原型,并且在初步规范评审后 [2],采用了一种更接近传统resize流程的方法。本规范的这个版本侧重于后者方法(不直接调用shelve方法)。在实施过程中会出现预料之外的问题,因此规范尽量避免深入到过低的实施细节,而是侧重于所需的一般步骤和已知问题。必要时会提出未解决的问题。

为什么调整大小?

我们进行resize是因为单元可以按flavor进行分片,而resize是用户(默认情况下)迁移从一个单元(旧flavor,gen1)到新flavor(gen2)的新单元的唯一非管理员方式。这有助于管理员/操作员清理旧的、使用旧硬件的单元。

术语

规范中使用的常用术语。

  • 源单元格:调整大小发起时实例“存在”的单元格。

  • 目标单元格:实例在跨单元格调整大小期间移动到的单元格。

  • 调整大小的实例:状态为 VERIFY_RESIZE 的实例。

  • 超级 conductor:在 split-MQ 部署中,超级 conductor 在“顶部”运行,可以访问 API 数据库,因此可以通过 RPC 与单元格通信并直接与单元格数据库通信。

假设

  • 不同单元的计算主机之间没有SSH访问权限。

  • 镜像服务(glance)、持久卷存储(cinder)和租户网络(neutron)跨越单元格。

目标

  • 从外部(API 用户、通知消费者)和内部(nova 开发人员)的角度来看,对整体调整大小流程的最小更改。

  • 在调整大小失败的情况下,保持轻松回滚到源单元格的能力。

策略规则

将添加一个新的策略规则 compute:servers:resize:cross_cell。它将默认为 !,这意味着不允许任何用户。这既向后兼容,又灵活,以便操作员可以确定其云中哪些用户允许执行跨单元格调整大小。例如,操作员可能只想允许系统级管理员或测试工程师最初执行跨单元格调整大小。

调整大小流程

本节描述了调整大小流程,直到服务器达到 VERIFY_RESIZE 状态为止。

API

API 将检查用户是否允许,通过新的策略规则,执行跨单元格调整大小 *并且* 源主机的 nova-compute 服务是否足够新以支持跨单元格调整大小流程。如果是,API 将修改 RequestSpec,以告诉调度器不要将主机限制在源单元格,但默认情况下源单元格将“首选”。

我们在API中执行此检查有两个主要原因

  1. 2.56 微版本 允许具有 admin 角色用户在冷迁移期间指定目标主机。目前,API 验证 目标主机是否存在,这仅适用于实例所在的单元格中的主机(因为请求上下文针对该单元格)。如果允许请求执行跨单元格调整大小,我们将调整目标主机检查以允许其他单元格。

  2. 当前,resize/migrate API操作是同步的,直到conductor RPC将请求发送到选定的目标主机上的 prep_resize()。在跨单元resize期间,如果conductor需要验证潜在的目标主机,这可能会有问题,因为REST API响应可能会超时。直到 2.34 microversion,live migrate API 存在相同的问题。如果允许请求执行跨单元resize,我们将从API到conductor进行RPC调用。

调度器

将引入一个新的 CrossCellWeigher,默认情况下将首选源单元格中的主机。将添加一个可配置的乘数来控制权重,以防操作员希望优先选择跨单元格迁移。对于所有非跨单元格移动操作,此称重器将是一个 noop。

请注意,一旦调度器选择了一个主选定的主机,所有备选主机都来自 同一个单元格

(超级)Conductor

conductor 的作用是同步协调两个单元格之间的调整大小。鉴于假设不同单元格中的计算主机无法通过 SSH 访问彼此,传统的通过 SSH 传输磁盘的调整大小流程将无法工作。

MigrationTask 将检查调度器选择的目的地,看看它们是否在另一个单元格中,如果是,则调用一组新的 conductor 任务来协调跨单元格调整大小。Conductor 将设置 Migration.cross_cell_move=True,这将用于 API 中控制确认/撤销逻辑。

一个新的 CrossCellMigrationTask 将协调以下子任务,旨在模仿传统的调整大小流程,并将利用新的计算服务方法。

目标 DB 设置

在我们可以执行目标主机中的任何检查之前,我们必须首先将实例及其相关数据(例如,块设备映射、网络信息缓存、实例操作等)填充到目标单元格数据库中。

为了在列出服务器时隐藏目标单元实例,目标单元中的实例将使用 hidden=True 字段创建,该字段将用于从API中过滤掉这些类型的实例。请记住,此时,API中的实例映射指向源单元,因此 GET /servers/{server_id} 仍然只会显示源单元中实例的详细信息。我们使用新的 hidden 字段来防止将错误的实例泄露到 GET /servers/detail。我们可能也会对相关的 migrations 表记录执行此操作,以避免将同一迁移记录的多个实例返回到 GET /os-migrations(巧合的是,migrations 表已经有一个未使用的 hidden 列)。

目标处的 Prep Resize

Conductor 将进行同步 RPC 调用(使用 long_rpc_timeout)到目标计算服务上的一个新方法 prep_snapshot_based_resize_at_dest,该方法将

  • 在目标单元格中调用 ResourceTracker.resize_claim() 到潜在的目标主机,以在开始调整大小之前声明资源。请注意,VCPU、MEMORY_MB 和 DISK_GB 资源实际上将在调度期间通过 placement 进行声明(分配),但我们需要进行 resize_claim() 以进行尚未在 placement 中建模的 NUMA/PCI 资源,并且为了创建 MigrationContext 记录。

  • 验证选定的目标主机,以确保端口和卷将工作。此验证将包括在目标主机上创建端口绑定,并确保卷附件可以连接到主机。

如果这两个步骤中的任何一个失败,目标主机将被拒绝。此时,conductor 任务将循环遍历备选主机,查找一个可以工作的主机。如果迁移在此阶段失败(耗尽主机),则迁移状态更改为 error,实例状态返回到其先前状态(要么是 ACTIVE 要么是 ERROR)。

instance.migration_context 从目标 DB 复制到源 DB。这对于 API 在稍后在目标单元格中生成客户时路由 network-vif-plugged 事件是必要的。

源处的 Prep Resize

Conductor 将进行同步 RPC 调用(使用 long_rpc_timeout)到源计算服务上的一个新方法 prep_snapshot_based_resize_at_source,该方法将表现得非常类似于 shelve 的工作方式,但也与 resize_instance 方法在传统调整大小期间的工作方式相吻合

  • 关闭实例。

  • 对于非卷支持的实例,创建并上传根磁盘的快照镜像。与 shelve 一样,此快照镜像将在调整大小成功完成后临时使用并删除。旧/新的 image_ref 将存储在 migration_context 中。

  • 销毁超visor 上的客户,但保留磁盘,即调用 self.driver.destroy(..., destroy_disks=False)。这对于断开源主机的卷和拔掉 VIF 必不可少,并且实际上与在正常调整大小期间在源主机上调用的 migrate_disk_and_power_off 方法非常相似。请注意,我们此时不会释放源主机上的跟踪资源,也不会更改数据库中的实例主机/节点值,以防撤销或从失败的迁移中恢复。

  • 删除旧的卷附件,并使用将在目标主机上使用的新的占位符卷附件更新 BlockDeviceMapping 记录。

  • 开放性问题:此时我们可能希望为目标主机激活端口绑定,但这可能不是必要的(在传统的resize过程中,源主机上的 resize_instance 不会这样做)。如果端口绑定到目标主机并且迁移失败,尝试通过重建在源 cell 中恢复实例可能无法工作(参见 bug 1659062),因此端口绑定可能应该延迟,或者我们必须小心地将它们回滚到源主机。

如果此时迁移失败,应删除创建的任何快照镜像。在源主机上恢复 guest 应该像硬重启服务器一样简单(允许服务器处于 ERROR 状态)。

在目标主机完成 Resize

此时我们将切换到目标 cell 中的目标主机,因此我们需要确保从源 cell 到目标 cell 的任何必要的数据库更新都已完成,例如 task_state、power_state、availability_zone 值、实例操作事件等。

Conductor 将使用 long_rpc_timeout 对目标计算服务上的新方法 finish_snapshot_based_resize_at_dest 进行同步 RPC 调用,该方法将与 unshelve 的行为非常相似,但也与传统 resize 期间的 finish_resize 方法的行为相吻合。

  • 应用迁移上下文并更新实例记录,以获取新的 flavor 和主机/节点信息。

  • 更新目标主机的端口绑定/PCI 映射。

  • 准备块设备(附加卷)。

  • 在 hypervisor 上启动 guest,这将连接卷并插拔 VIF。将使用新的 flavor,如果之前为非卷支持的实例创建了快照镜像,则该镜像将用于根磁盘。此时,virt 驱动程序应等待从 API 路由的 network-vif-plugged 事件,然后再继续。

  • 删除临时快照镜像(如果已创建)。这与 unshelve 的工作方式类似,其中 shelved 快照镜像会被删除。此时删除快照镜像是可以的,因为 guest 已经在目标主机上启动,并且如果需要在源主机上进行 revert 或恢复,源磁盘仍然在源主机上。

  • 将实例标记为已 resize。

在 conductor 中,我们需要

  • 将目标 cell 实例记录标记为 hidden=False,以便在列出服务器时显示它。请注意,由于 API 过滤器 复制实例记录,即使用户此时正在列出服务器,也只会返回一个实例副本。

  • 更新实例映射,以指向目标 cell。这样可以确保 confirm/revert 操作将在目标 cell 中的 resize 实例上执行,而不是在源 cell 中销毁的 guest 上。请注意,我们可以在目标主机上完成 resize 之前执行此操作,但最好将此操作推迟到实例在目标主机上成功 resize 后,因为如果失败,我们希望能够重建到源 cell 以恢复实例。

  • 将源 cell 实例记录标记为 hidden=True,以在列出服务器时将其隐藏。

Confirm 流程

在确认 resize 的服务器时,如果 Migration.cross_cell_move 值为 True,API 将

  • RPC调用源计算主机以销毁guest(包括磁盘),类似于 driver.confirm_migration 方法,并删除move claim(释放源节点的跟踪资源使用量)。

  • 删除基于迁移的资源分配,针对源 compute 节点资源提供程序(这可以在源 compute 或 API 中发生)。

  • 从源单元数据库中删除实例及其相关记录。

  • Migration.status 更新为目标 cell DB 中的 confirmed

  • 删除目标 cell DB 中实例上的迁移上下文。

  • 根据目标 cell DB 中实例的当前 power_state,将实例 vm_state 更改为 ACTIVESTOPPED(用户可能已手动打开 guest 以在确认 resize 之前对其进行验证)。

Revert 流程

与 confirm 流程类似,cross-cell revert resize 将通过 API 中的 Migration.cross_cell_move 字段识别。如果为 True,API 将 RPC cast 到一个新的 conductor 方法 revert_cross_cell_resize,该方法将执行一个新的 CrossCellRevertResizeTask。该任务将

  • 根据目标 cell 数据库的内容,更新源 cell 数据库中的实例及其相关记录。这对于以下内容尤其重要:

    • BDM,因为您可以附加/分离卷到/从 resize 的服务器。

    • API 在目标 cell 中创建的 REVERT_RESIZE 实例操作记录。这需要在源 cell compute 中跟踪 revert 期间的事件。

    幸运的是,API 不允许附加/分离端口或更改 resize 服务器上的服务器标签,因此我们不需要将这些复制回源 cell 数据库。

  • 更新实例映射,以指向源 cell。这需要在源 cell 中启动之前发生,以便从 neutron 路由 network-vif-plugged 事件。

  • 将目标 cell DB 实例标记为 hidden=True,以便在 revert 时将其隐藏在 API 中列出服务器时。

  • RPC 调用目标 compute 以终止实例(销毁 guest,断开卷和端口,释放跟踪的资源)。

  • 从目标单元数据库中销毁实例及其相关记录。

  • Migration.status 更新为源 cell DB 中的 reverted

  • RPC 调用源 compute 以 revert 迁移上下文,应用旧的 flavor 和原始镜像,附加卷并更新端口绑定,打开 guest(如在 driver.finish_revert_migration 中一样),并将迁移记录在 placement 中持有的源节点分配交换到实例记录。

    请注意,resize 期间保留源磁盘的替代方案是在 revert 期间使用快照镜像并直接从该镜像启动(而不是从保留的磁盘启动)。但是,这意味着可能需要将快照镜像下载回源主机,并确保在 confirm 和 revert 时都清理快照镜像,而不仅仅是在 resize 结束时。它还会使在 resize 失败的情况下通过简单地硬重启它来恢复 guest 变得复杂。

限制

  1. 定期任务 _poll_unconfirmed_resizes,可以配置为自动确认目标主机上的待处理 resize,不支持 cross-cell resize,因为执行此操作需要向上调用 API 以确认 resize 并清理源 cell 数据库。在 conductor 服务中编写一个新的定期任务作为未来的增强功能,可以协调自动 cross-cell resize confirm。

已知问题

  1. 与其让 conductor 在 resize 期间使用 long_rpc_timeout 配置选项进行同步 RPC 调用,不如可以添加一个新的选项专门用于 cross-cell(基于快照)resize 操作。考虑到大型磁盘的快照可能需要很长时间才能上传(或下载),最好添加新的选项来控制这些超时。对于此功能的初始版本,我们将重用 long_rpc_timeout,如果需要,我们可以在将来添加更细粒度的选项。

  2. API 中的一个语义差异是 resize 期间实例操作记录下的不同事件,因为事件是通过 compute 方法上的 wrap_instance_event 装饰器创建的,并且在使用具有新名称的新方法时,与正常 resize 相比,将会有新的事件。这可以通过将特定名称传递给装饰器而不是像今天一样只使用函数名称来解决。鉴于对操作记录下的事件没有 API 保证,并且这始终是 API 泄露的内部细节,我们不会尝试覆盖新的函数/事件名称,例如,在调用 prep_snapshot_based_resize_at_dest 方法时记录 compute_prep_resize 事件。

边缘情况

  1. 如果用户在 VERIFY_RESIZE 状态下删除服务器,API会确认resize以清理源主机,然后再从目标主机删除服务器 [3]。这段代码需要考虑到跨单元resize并进行适当的清理(清理源主机并从源单元删除记录)。

  2. 在 API 中 路由网络事件 时,如果实例具有迁移上下文,它将基于 id 而不是 uuid 查找迁移记录,如果迁移上下文是在不同的 cell 数据库中创建的,则这可能是错误的,因为迁移记录上的 id 主键不同。尚不清楚这是否会成为问题,但可以通过几种方式处理

    • 将 migration.uuid 存储在迁移上下文中,并使用 uuid 而不是 id 查找迁移记录。

    • 将迁移上下文从目标 cell DB 复制到源 cell DB 时,更新 MigrationContext.migration_id 以匹配源 cell 迁移记录的 Migration.id

  3. 可以将卷附加/分离到resize的服务器。因此,在revert期间将这些块设备映射更改从目标单元DB镜像到源单元DB会增加复杂性,但这是可管理的 [4]。对resize的服务器执行此操作的能力并不为人所知,并且可能未正式支持,以保留在revert期间附加的任何卷,但由于这是今天有效的工作方式,我们应该尝试为跨单元resize提供支持。

备选方案

Lift and shift

用户(或云操作员)可以强制现有服务器进行快照、销毁,然后在新的 cell 中使用新的 flavor 从快照重新创建。假设部署已经具有某种用于在站点或区域之间移动资源的工具。虽然正常的 resize 已经会中断正在运行的工作负载,但这种替代方案对于附加了特定卷和端口的情况尤其成问题,即 IP(地址)和服务器 UUID 会发生变化。此外,它将需要所有多 cell 部署来协调自己的 cross-cell 迁移工具。

Shelve 编排

本规范的替代设计可以在PoC [1] 和本规范的初始版本 [2] 中找到。该方法试图重用现有的shelve和unshelve函数来

  • 快照并从源 cell 卸载。

  • 在目标 cell 中从快照中 unshelve。

  • 在回滚时,从目标 cell 卸载并然后在源 cell 中 unshelve。

API、调度器和数据库操作逻辑类似,但由于使用了 shelve,实例是从源 cell 卸载的,这可能会使回滚到原始源服务器变得复杂,并需要重新调度到源 cell 中的不同主机。

此外,该方案导致了与 shelve 相关的新的任务状态和通知,这些在正常的调整大小中找不到,这可能会令人困惑,并且使 shelve/unshelve 代码中的逻辑变得复杂,因为它必须处理调整大小的情况。

将此规范中提出的方案与 shelve 方案进行比较

优点

  • 使用新的方法来控制任务状态和通知,更简洁;没有复杂的双重用途逻辑来处理调整大小的 shelve,即不要重复疏散/重建的债务。

  • 源实例基本未受影响,这应该使回滚和恢复更简单。

缺点

  • 大量新代码,其中一些代码与 shelve/unshelve 大量重复。

从长远来看,尝试混合方法(此规范中的方案)会更好,即使用新的计算方法来控制通知和任务状态,以更接近传统的调整大小流程,但混合 shelve/unshelve 风格的操作,例如快照、guest 销毁/生成。

数据模型影响

  • 将在 migrations cell DB 表和相关的版本化对象中添加一个 cross_cell_move 布尔列,默认值为 False。

  • 将在 instances cell DB 表和相关的版本化对象中添加一个 hidden 布尔列,默认值为 False。

REST API 影响

REST API 的显式请求/响应模式不会发生变化。保持相同的任务状态转换,并在最后保持实例处于 ACTIVESHUTDOWN 状态等正常的调整大小语义将保持不变。

当实例正在调整大小并且在两个 cell 中都有记录时,API 必须小心过滤掉跨 cell 列出这些记录时的重复实例和迁移记录(使用 hidden 字段)。

安全影响

策略规则 部分所述,将添加一个新的策略规则来控制哪些用户可以执行跨 cell 调整大小。

通知影响

与 API 中的任务状态转换类似,通知应尽可能保持相同。例如,目标处 Prep Resize 阶段应发出现有的 instance.resize_prep.start/end 通知。源处 Prep Resize 阶段应发出现有的 instance.resize.start/end/error 通知。

更大的影响将是对于具有每个 cell 的通知队列的部署,因为通知将从一个 cell 停止并在另一个 cell 中启动,或者在调整大小期间混合(目标处的 prep 在目标 cell 中,而源处的 prep 在源 cell 中)。不过,这可能对 ceilometer 等通知消费者产生什么影响尚不清楚。

如果需要,可以添加新的版本化通知(或现有通知中的字段)来指示正在执行跨 cell 调整大小,作为此蓝图的一部分或作为未来的增强功能。

其他最终用户影响

如上所述,实例操作事件和版本化通知行为可能不同。

性能影响

显然,由于涉及数据库协调以及需要从源 cell 拍摄镜像支持实例的快照并在目标 cell 中下载快照镜像,因此跨 cell 调整大小的性能将低于正常的调整大小。

此外,启用此功能的部署可能需要扩展其 conductor worker,这些 worker 将执行大量的编排工作,而不是像正常调整大小那样进行跨计算协调。同样,rpc_conn_pool_size 可能需要增加,因为涉及同步 RPC 调用。

其他部署者影响

部署者将能够控制谁可以在其云中执行跨 cell 调整大小,并能够调整调整大小期间使用的参数,例如 RPC 超时时间。

开发人员影响

将添加具有以下签名的新的 can_connect_volume 计算驱动程序接口

def can_connect_volume(self, context, connection_info, instance):

这将用于在验证步骤期间,以确保附加到实例的卷可以连接到目标 cell 中的目标主机。代码本身将相对较小,只需涉及驱动程序现有的卷附加/分离操作的一部分。

升级影响

有三个主要的升级注意事项来支持此功能。

  • RPC:由于计算和 conductor 服务的 RPC 接口发生了变化,因此在可以执行跨 cell 调整大小之前,这些服务自然需要升级。

  • Cinder:由于验证依赖于卷附件,因此 cinder 需要运行至少 Queens 级别的代码,并提供 3.44 微版本

  • Neutron:由于验证依赖于端口绑定,因此 neutron 需要运行至少 Rocky 级别的代码,并启用 Port Bindings Extended API 扩展。

实现

负责人

主要负责人

Matt Riedemann <mriedem.os@gmail.com> (irc: mriedem)

其他贡献者

工作项

从高层来看,这是需要按顺序进行的更改系列,尽管实际上,控制平面更改中的一些可以在任何顺序下进行,只要冷迁移任务更改在最后。

  • DB 模型更改 (migrations.cross_cell_move, instances.hidden)。

  • 各种版本化对象更改,用于跟踪 RequestSpec 中的跨 cell 移动,通过 UUID 查找 Migration,从现有数据创建 InstanceAction 和 InstanceActionEvent 记录等。

  • 调度器更改,以便在跨 cell 移动期间从多个 cell 中选择目标主机,并对它们进行加权,以便默认情况下优先选择“源”cell。

  • 可能的 MigrationContext 对象更改,用于添加新的字段,例如 old_image_ref, new_image_ref, old_flavor, new_flavor, old_vm_state(这将取决于实现)。

  • nova-compute RPC 接口更改,用于目标处的 prep/validate,源处的 prep 以及源处的完成调整大小操作。

  • 添加新的 conductor 任务,用于编排跨 cell 调整大小,包括回滚调整大小。

  • API 连接更改,以处理确认/回滚跨 cell 调整大小。

  • 添加新的策略规则,并使现有的调整大小流程使用它来告诉调度器目标主机是否可以来自另一个 cell,如果目标主机来自另一个 cell,则运行新的跨 cell 调整大小 conductor 任务来编排调整大小,而不是传统的计算编排流程(其中源和目标 nova-compute 服务通过 SSH 和 RPC 进行通信)。

依赖项

测试

PoC 更改中的现有功能测试应该能很好地了解需要测试的各种问题。一些明显的测试包括

  • 调整大小基于镜像和基于卷的服务器。

  • 确保在调整大小的各个点(例如,在服务器处于 VERIFY_RESIZE 状态、确认后和回滚后)Placement 服务中的分配和 os-hypervisors API 的资源报告是准确的。

  • 确保正确管理卷附件和端口绑定,即不泄漏任何资源。

  • 服务器及其相关虚拟设备(卷和端口)上的标签在调整大小到目标 cell 后仍然存在。

  • VERIFY_RESIZE 状态下附加/分离到/从服务器的卷在调整大小确认/回滚的情况下得到正确管理。

  • 在调整大小期间,跨 cell 跨越的资源,例如服务器及其相关的迁移,不会在 API 中重复列出。

  • 使用容量已满的计算进行调整大小,这意味着在回滚时,我们只能将实例与旧配置一起放回源 cell 中的源主机上。

  • 确保启动/结束事件/通知与正常的同 cell 调整大小一致。

  • 从活动和停止的服务器进行调整大小,并断言在确认和回滚调整大小后,原始状态得以保留。

  • 删除调整大小的服务器,并断言资源和 DB 记录从源 cell 和目标 cell 中得到正确清理。

  • 测试一个故障场景,其中服务器通过在源 cell 中重建来恢复。

将在整个系列结束时添加各种更改的单元测试,功能测试涵盖集成的流程。负/错误/回滚场景也将通过单元测试和功能测试进行覆盖,具体取决于情况。

由于没有直接的 API 更改,Tempest 测试不太适合此更改。但是,我们真正应该拥有的,并且可以说自 Pike 以来就应该拥有的是一个多 cell CI 作业。但是,如何创建多 cell CI 作业的细节尚不清楚,因为它需要与遗留 devstack-gate 工具集成,或者,如果可能,新的 zuul v3 工具。

文档影响

计算管理员 调整大小指南 将更新,以从操作的角度详细记录跨 cell 调整大小,包括故障排除和灾难恢复细节。

计算 配置指南 将更新,以包含新的策略规则和添加的任何配置选项。

计算 服务器概念指南 也可能需要更新,以说明任何面向用户的更改,例如跨 cell 调整大小期间服务器的状态转换。

参考资料

Stein PTG 讨论

邮件列表讨论

历史

修订版

发布名称

描述

Stein

引入