AIP-217 不可达资源
编号 | 217 |
---|---|
原文链接 | https://google.aip.dev/217 |
状态 | 批准 |
创建日期 | 2019-08-26 |
更新日期 | 2019-08-26 |
有时,用户可能会请求一系列资源,而其中某些资源暂时不可用。最典型的场景是跨集合读。例如用户可能请求返回多个上级位置的资源,但其中某个位置暂时不可达。此时仍然需要向用户提供所有可用资源,同时告诉客户有部分缺失。
指南
如果查询数据的方法由于若干资源暂时不可达而部分失败,应答消息 必须 包含一个域来表明这一点:
message ListBooksResponse {
// 符合请求的书籍。
repeated Book books = 1;
// 下一页的令牌(如果还有符合请求的书籍)
string next_page_token = 2;
// 不可达资源。
repeated string unreachable = 3 [
(google.api.field_behavior) = UNORDERED_LIST
];
}
- 域 必须 是一个重复字符串域, 应该 命名为
unreachable
。 - 域 必须 包含不可达的、或者阻碍访问所请求集合的资源名字,例如所请求集合的上级资源不可达。
- 例如整个位置不可达,阻止了访问所请求的本地资源集合,则包含位置资源。
- 域 必须 包含 服务相对 资源名, 不得 包含完整资源名、资源URI或简单资源标识。有关定义请参考AIP-122。
- 例如
Book
资源不可达,则 服务相对 资源名"shelves/scifi1/books/starwars4"
包含在unreachable
中,而非 完整 资源名"//library.googleapis.com/shelves/scifi1/books/starwars4"
、/上级相对/ 资源名"books/starwars4"
、资源标识"starwars4"
或资源URI。
- 例如
- 应答 不得 提供导致所需资源不可达的问题的任何其他信息。
- 例如应答不能包含额外的域,包括每个
unreachable
条目的错误原因。
- 例如应答不能包含额外的域,包括每个
- 服务 必须 提供方法,让用户能够发出具体请求,接收额外错误信息。例如使用标准的Get或List方法,请求不可达集合的上级资源。
- 服务 必须 允许用户使用更严格的参数重发请求。
- 出现在
unreachable
中的资源名字 可能 是异构的。unreachable
域 应该 在文档中记录可能包含的资源,注明资源列表可能在将来扩展。- 例如整个位置和不同位置的特定资源都不可达,那么不可达位置的名字(如
"projects/example123/locations/us-east1"
)和不可达资源的名字(如"projects/example123/locations/europe-west2/instances/example456"
)都将出现在unreachable
中。
unreachable
域 不得 在列表内提供语义上有意义的顺序或结构。换句话说,unreachable必须 是一个无序列表。- 因此
unreachable
域 必须 使用UNORDERED_LIST
域行为注释(参考AIP-203)。
- 因此
重要 如果按照规范要求,由于位置或资源不可达,无法返回数据(例如请求列出某个出版商的资源,但该出版商不可达),服务必须终止整个请求,返回错误信息。
分页
在准备分页远程过程调用(例如AIP-132标准List方法)结果时,如果服务遇到不可达资源或集合, 必须 遵照下列执行:
- 在
unreachable
应答域中包含不可达资源的资源名。- 资源名字 必须 是不可达资源或集合的最适当的范围。
- 例如某地区的特定区域不可达,不可达资源名是区域位置(如
projects/example/locations/us-west1-a
)。如果整个地区不可达,资源名是区域位置(如projects/example/locations/us-west1
)。
- 例如某地区的特定区域不可达,不可达资源名是区域位置(如
- 如果发现资源不可达,无论分页参数(如
order_by
)如何限制, 必须 包含资源名。
- 资源名字 必须 是不可达资源或集合的最适当的范围。
- 如果先前不可达资源恢复可用,分页参数也允许包含这些资源,在后续页中添加它们。
- 根据分页参数确定包含哪些资源。如果用户没有设定排序规则,遵守文档要求的默认排序规则。
- 例如在有序分页调用中,地区
projects/example/locations/us-west1
在第一页中不可用。如果包含该地区资源将违反排序规则,那么这些资源不包含在后续页中。 - 类似的,如果重发同一请求,先前不可达资源恢复可用, 必须 在分页参数约束下添加它们。
- 如果适当上调资源范围后,不可达资源名数量仍然超过文档要求的最大值,限制应答中返回的不可达资源名数量。
- 最大值 必须 直接记录在
unreachable
域注释中。 - 最大值与调用者设定的
page_size
无关。
- 最大值 必须 直接记录在
保持原有行为
如果修改分页行为会产生AIP-180描述的不兼容变更,服务 可以 继续保持以前实现的 unreachable
分页行为,但 必须 在 unreachable
域文档中直接记录具体行为。
适配部分成功
现存API中,默认行为不同于上述指南的(例如API调用返回错误状态而非部分结果),适配 unreachable
模式时 必须 执行下列操作:
- 必须 保持默认行为,避免行为变更不兼容。
- 例如默认行为是当任何位置不可达时返回错误,*必须* 保持原默认行为 。
- 请求消息 必须 包含
bool return_partial_success
域。 - 应答消息 必须 包含标准
repeated string unreachable
域。 - 上述两域 必须 同时添加。
如果请求中的 bool return_partial_success
域设定为 true
,API 必须 按照上述指南,填写 repeated string unreachable
应答域。
message ListBooksRequest {
// Standard List request fields...
// Setting this field to `true` will opt the request into returning the
// resources that are reachable, and into including the names of those that
// were unreachable in the [ListBooksResponse.unreachable] field. This can
// only be `true` when reading across collections e.g. when `parent` is set to
// `"projects/example/locations/-"`.
bool return_partial_success = 4;
}
message ListBooksResponse {
// Standard List Response fields...
// Unreachable resources. Populated when the request opts into
// `return_partial_success` and reading across collections e.g. when
// attempting to list all resources across all supported locations.
repeated string unreachable = 3 [
(google.api.field_behavior) = UNORDERED_LIST
];
}
部分成功的粒度
如果请求的 bool return_partial_success
域设定为 true
,而请求范围超出了API能够合理判断不可达资源能力的粒度,API 应该 返回 INVALID_ARGUMENT
错误,附带说明问题的细节。例如某个API仅在跨集合读时支持 return_partial_success
,如果请求范围限定为特定上级资源集合,则返回 INVALID_ARGUMENT
错误。API支持的粒度 必须 在 return_partial_success
域文档中记录。
理由
使用服务相对资源名
根据AIP-122定义的相对资源名通常是在服务内部或跨服务引用资源的最佳选择,尤其在外部服务明确时。完整资源名严格来说不太好用(例如需要在客户端进行解析),并且对于 unreachable
来说过于具体。资源URI并非与传输无关,因此它们在gRPC标准方法中不可用,而简单资源标识无法提供充足信息,准确指出在异构资源列表中哪个资源不可达。
在应答中提供最少额外错误详情
不可达资源的上下文可能存在敏感信息,系统状态在调用之间也是变化的。因此最好使用更具体的远程过程调用,依赖服务获取特定资源或上级资源的更多详情。这可以让服务在处理上级资源时进行全面检查、判定系统状态。而不是将可能涉密或过期的信息,胡乱塞入遭遇资源不可达的调用中。
不对 unreachable
进行排序
要在许多API之间达成统一, unreachable
内容不存在特定的、有序的语义结构非常重要。如果每个API在标准域中生成特定顺序,无论是客户端或服务器如何实现,都无法保证正确。
每个页都包含 unreachable
资源
每个页都包含 unreachable
资源,允许终端用户立即识别页面是否完整,不需要遍历所有结果。用户未必会分页到末尾,重要的是尽快在页中提示缺少不可达资源。此外,这允许用户识别潜在问题,在后续调用中处理。最后,保留不可达资源信息直到分页末尾,这需要服务在完全隔离的API调用中保持一组相互独立的状态。
使用请求域作为选项
引入新的请求域作为适配部分成功行为的选项,是即能传达用户意图,又能保持默认行为向后兼容的最好的办法。另一种选择,改变默认行为,加入 unreachable
应答域,将导致不向后兼容的变更。预期当某个资源不可达时遇到失败的用户,可能会认为应答成功表示已经包含全部资源。
同时引入域
同时引入请求和应答域,是为了防止只添加一个域时,可能出现无效的中间状态。如果只添加 unreachable
,用户可能假定域为空意味着已经返回全部资源,而实际未必如此。如果只添加 return_partial_success
,用户将无法得知哪些资源不可达。
部分成功的粒度限制
在请求范围的某个粒度级别上,API可能完全无法枚举不可达资源。例如全局性API可能无法提供本地集合级别的粒度。在此场景中,如果 return_partial_success=true
时主动返回错误,可以避免用户遭遇风险:系统存在问题,但用户未收到不可达列表,误以为已经检索全部资源。这与本指南一致:对于无法完整执行的请求,主动返回失败。
历史
分页指南
最初关于填充 unreachable
域的指南的核心思路是:将这些内容视为分页结果。这意味着分页资源与不可达资源不会出现在同一应答(即页)中。用户需要遍历所有结果,才能发现是否存在不可达资源。有关更改的原因,请参考理由部分。
进一步阅读
- 关于跨集合读,请参考AIP-159。
修订记录
- 2024-07-29 修改指南格式,添加具体的资源名格式
- 2024-07-26 修改分页指南要求。
- 2024-07-19 添加适配部分成功的指南。