利用版本控制发展 API

Azure 逻辑应用、Microsoft Power Automate 或 Microsoft Power Apps 的自定义连接器必须提供 OpenAPI 规范文件。 此 OpenAPI 规范定义称为操作的各入口点。 每个操作都有唯一的 operationId 和唯一的 urlPathHttpVerb 组合。

{
    "/items": {
        "get": {
            "summary": "Get rows",
            "description": "This operation gets a list of items.",
            "operationId": "GetItems"
        },
        "post": {
            "summary": "Insert row",
            "description": "This operation inserts an item.",
            "operationId": "PostItem"
        }
    }
}

随着功能的不断添加和扩展,这些操作会不断增多并发生变化。 某些更改只是附加性的,并不一定违背客户端和服务器之间的协定。 这类更改可能包括:添加新参数、返回更多数据或允许更灵活的输入。

但很多更改实际上可能会违背 OpenAPI 规范中所述的协定。 删除参数,不再支持某些输入,或更改输入、输出或操作本身的含义和行为都属于“中断性变更”这一类别。

为了安全地演变 API,请务必遵循客户端可以导航的模式。 API 负责维护后向兼容性、传达意图并描述版本控制属性。 客户端负责显示或隐藏已弃用、已过期或可能有更新版本的操作。 通过这种方式,操作可以在各个时段不断增多和改进,而不会使依赖于它们的应用程序过于脆弱。

API 注释

OpenAPI 不提供针对操作版本控制的内部支持。 为了实现我们的目标,我们通过 x-ms-api-annotation 对象完成大部分工作,在全局范围和操作范围应用此对象。 全局对象包含的属性作为一个整体应用到 API:

{
    "x-ms-api-annotation": {
        "status": "Preview"
    }
}
属性 默认值 说明
status "Preview" "Production" "Preview" API 的整体状态—最开始为预览状态,然后根据使用情况和稳定性要求升级到生产状态

在操作范围,此对象包含更详细的属性。 此对象之外还有其他属性,它们应用于并参与版本控制的演变过程:

{
    "deprecated": true,
    "x-ms-api-annotation": {
        "status": "Production",
        "family": "MyOperation",
        "revision": 2
    }
}
属性 默认值 描述
deprecated null false true false 指示此操作是否已弃用
x-ms-visibility null "" "Important" "Advanced" "Internal" "" 此操作预期的可见性和突显度,其中的 null"" 表示正常状态
status "Preview" "Production" "Production" 操作的状态—这可能不同于 API 本身的状态,但如果未指定,则将从顶级 API 状态继承
family {常见操作名称} operationName 名称,应用于此操作的每个修订版本
revision 数值(1、2、3...) 1 指定操作系列的修订版本
expires ISO8601 日期 (无) 针对客户端的可选提示,指示预计的支持终止日期

当客户端不再需要使用此操作时,可以将弃用设置为 trueOpenAPI 固定字段规范中存在此属性。

可见性用于指示操作预期的相对突显度。 可见性为 "Important" 指示操作应靠近列表顶部,显示在醒目的位置。 可见性默认设置为 normal(由 null 或空字符串 "" 表示),表示该操作将显示在列表中,很可能列在 Important 操作之后。 可见性为 "Advanced" 指示操作可能靠近列表底部,甚至最初是隐藏于 expando 控件之后。 高级操作可能更难以使用、不太常用或者应用面较窄。 可见性为 "Internal" 指示操作不应向用户公开,而只应在内部使用。 内部操作在编程方面很有实用价值,但不适用于最终用户。 这样标记内部操作是为了在弃用过程中在任何类型的 UI 中隐藏它们,而无需从 API 中真正将其删除(将它们真正删除会导致重大更改)。

Status 指示 API 或操作的稳定性。 "Preview" 指示操作或 API 是新的,并且可能未经验证。 “预览”用于指示生产系统应该慎重使用依赖项。 在操作或 API 变得更加完善,且经验证符合可靠性、成功率和可伸缩性标准后,就可以有意地将其升级到 "Production" 状态。

以下指标要求通常适用于需要升级到 "Production" 状态的操作:

  • 三周内的成功率为 80%
    • 定义为 2xx 范围内的 HTTP 响应代码的百分比
  • 持续三周时间保持 99.9% 的可靠性
    • 定义为非 5xx 范围(502、504 和 520 不包含在计算内)内的 HTTP 响应代码的百分比

Family 指示概念上相同但修订版本不同(可能存在中断性变更)的操作之间的关系。 如果多个操作应视作彼此的修订版本,这些操作将使用同一系列名称,并按各自的唯一修订号进行排序。

Revision 指示操作系列中操作的演变顺序。 一个系列中的每个操作都有一个修订号,它是一个整数索引,暗示存在顺序关系。 如果修订号为空,操作将被视为修订版 1。 如果有较新版本的操作可用,客户端应将它们显示在较为醒目的位置,更加特意地加以推荐,但仍应该允许用户选择尚未弃用的可能较旧的修订版本。

到期是可选属性,它指示可能的生命周期终止时间,届时不再保证对操作的支持。 只可为已弃用的操作设置,当前该属性未反映在任何接口中。

操作生存期

操作的生存期可以预测,这一点可以通过示例来演示。

起点

最初,操作可能不一定指示任何有关修订版本的内容。 这些操作已应用了默认值,因此在等效于 operationId 的家族名称中被视为修订版 1。

{
    "/{list}/items": {
        "get": {
            "summary": "Get rows",
            "description": "This operation gets a list of items.",
            "operationId": "GetItems"
        }
    }
}

它和这个更加明确的定义是等效的:

{
    "/{list}/items": {
        "get": {
            "summary": "Get rows",
            "description": "This operation gets a list of items.",
            "operationId": "GetItems",
            "deprecated": false,
            "x-ms-api-annotation": {
                "status": "Production",
                "family": "GetItems",
                "revision": 1
            }
        }
    }
}

操作启动

API 的大部分演变结合起来就构成了一种新操作。 例如,新方法和现有方法的新修订版本。 若要安全地启动新版本,请以下述方式调整 OpenAPI 规范:

{
    "/{list}/items": {
        "get": {
            "summary": "Get rows (V1 - downplayed)",
            "description": "This operation gets a list of items.",
            "operationId": "GetItems",
            "deprecated": false,
            "x-ms-visibility": "advanced",
            "x-ms-api-annotation": {
                "status": "Production",
                "family": "GetItems",
                "revision": 1
            }
        }
    }
    "/v2/{list}/items": {
        "get": {
            "summary": "Get rows (V2 - new hotness)",
            "description": "This operation gets a list of items.",
            "operationId": "GetItems_V2",
            "deprecated": false,
            "x-ms-api-annotation": {
                "status": "Preview",
                "family": "GetItems",
                "revision": 2
            }
        }
    }
}

重要

请注意,GetItems V2 具有唯一的 operationId,最初以预览状态列出。 另请注意,GetItems v1 的可见性现为“高级”,因此不会显示在醒目的位置。

操作弃用

有时,如果现有的 V1 入口点继续提供价值,并且没有令人信服的弃用理由,那么它们就会无限期地保留下来。 但是,许多 V2 入口点都会有意取代 V1 入口点。 为了安全地执行此操作,所有流量都应达到原始操作的标称零值。 遥测确认此情况之后,便可以进行以下更改:

{
    "/{list}/items": {
        "get": {
            "summary": "Get rows (deprecated)",
            "description": "This operation gets a list of items.",
            "operationId": "GetItems",
            "deprecated": true,
            "x-ms-api-annotation": {
                "status": "Production",
                "family": "GetItems",
                "revision": 1
            }
        }
    }
    "/v2/{list}/items": {
        "get": {
            "summary": "Get rows",
            "description": "This operation gets a list of items.",
            "operationId": "GetItems_V2",
            "deprecated": false,
            "x-ms-api-annotation": {
                "status": "Production",
                "family": "GetItems",
                "revision": 2
            }
        }
    }
}

重要

注意,GetItems V1 现标记为已弃用。 这是弃用操作的最终转换。 GetItems V2 现已完全替换 GetItems V1。

为什么要多此一举?

坚持进行操作版本控制有诸多原因。 它的主要目的是确保当用户将连接器操作集成到其数据流中时,Azure 逻辑应用和 Power Automate 等客户端能够继续正常工作。 在以下情况下,应使用上述方法对操作进行版本控制:

  • 增加了操作的新修订版本
  • 现有操作添加或删除了参数
  • 现有操作更改了大量输入或输出

严格来讲

在某些情况下,可能无需进行版本控制—但在进行版本控制的情况下,应小心谨慎,并且应执行大量测试,确保没有忽略可能会导致用户意外中断的极端情况。 下面提供了一个周到细致的简短列表,其中列出了可以不进行版本控制的情况:

  • 添加了一项新操作。

    具体来说,这不会中断现有客户端。

  • 现有操作中添加了新的可选参数。

    这不会中断现有调用,但必须仔细考虑。

  • 现有操作对行为进行了小改动。

    根据更改的性质和用户依赖的内容,这可能不会中断现有调用方。 这是最危险的一种情况,因为输入接受、输出生成、计时或处理等方面存在显著差异可能会影响操作行为,从而难以确定更改的风险。

我们始终建议,在进行任何重要的 API 更改时,请谨慎操作,并以迭代方式进行修订。

提供反馈

我们非常感谢大家提出有关连接器平台问题或新功能想法的反馈。 要提供反馈,请转到提交问题或获取连接器帮助,然后选择反馈类型。