Skip to content

Latest commit

 

History

History
229 lines (131 loc) · 11 KB

sdk-design-guidelines.md

File metadata and controls

229 lines (131 loc) · 11 KB

UCloud SDK Design Guidelines

[TOC]

概览

设计准则

单调性

SDK 应采用语义化版本,并始终保持版本的单调递增,并遵守语义化版本的兼容性承诺。

一致性

对于多语言、交付渠道之间具有共同性质的部分,应尽力而为构造单一的事实来源,以保障多个客户端工具之间的最终一致性。

对于抽象定义与概念,应在多个客户端工具之间保持一致,以使用户在使用不同客户端工具时,可以低成本地迁移。

可访问性

对于每个语言,SDK 应以符合该语言惯用法的方式来设计,并通过语义标注技术(如注释、注解等),为 IDE 等开发工具提供良好的支持,使用户在脱离文档的前提下依然能够理解其含义。

可观测性

客户端 SDK 应对于内部运行时具备一定的可观测能力,对外暴露相应的扩展机制,以使故障发生时,用户可以高效地定位问题根因。

术语表

UCloud SDK

UCloud SDK 是一种客户端工具,使用户采用流行的通用编程语言,调用 UCloud 的云上命令式 API。

UCloud SDK 核心(Core)

SDK 核心是用于实现 SDK 公共逻辑的一系列工具。

UCloud SDK 服务(Service)

SDK 服务是 UCloud 公有云各产品服务在 SDK 语境下的统称,例如云主机、网络等。

架构风格

架构风格是描述特定领域模式的一组相互协同的架构约束。详见 Roy Thomas Fielding 博士的论文以及 UCloud 开发者工具领域的架构风格定义。

SDK 适用于三种架构风格(命令式、声明式、交互式)中的命令式 API。

前置语

  • 必须
  • 禁止
  • 应该
  • 不应该
  • 可以

设计

配置

目标:提供一种机制,使用户可以面向一组客户端对象配置公共属性,方便其抽象和复用。

架构约束

必须 遵守 [UCloud 配置公约](#UCloud 配置公约)以共享和加载客户端全局配置,使多个开发工具间拥有相类似的配置方式,减轻用户认知负担。

必须 允许客户端配置覆盖全局配置。

必须 允许多个客户端实例采用不同的配置,例如实例化多个客户端对象,发送请求给不同的代理端点。

中间件

目标:提供一种机制,为 SDK 调用的每一个生命周期添加额外的钩子,使用户可以对 API 请求的生命周期自定义面向切面的上下文处理机制。

架构约束

必须 允许用户自定义请求、响应和错误处理的处理逻辑。

应该 使 SDK 请求生命周期内的默认逻辑,都作为中间件来处理,例如鉴权、日志等。

参数变换与校验

通常情况下,客户端 SDK 包括一系列向服务端发起请求的方法,但产品服务并非直接将参数传递给服务端点,而是经过客户端 SDK 的一系列准入控制与变换的操作。

目标:在语言的惯用法与云服务提供商的架构风格之间形成一个映射,同时在客户端阻止无效请求的发起

架构约束

必须 在客户端发起实际请求前,完成参数的校验与变换操作,以使用户低成本的发现和复现参数问题。

必须 在该层次完成各编程语言原生的复杂容器类型到 .N 字段命名风格的变换,以使用户可以采用最熟悉的对象模型,而无需关注序列化协议。

应该 使校验机制包括空值校验和类型校验,以确保送达服务端的请求,一定符合 API 契约。

网络传输

目标:为与网络交互的边界独立抽象一层,以提供单独的切面、故障注入等逻辑。

架构约束

必须 明确区分网络请求对象,和业务请求对象,以使用户对于具体的网络协议无感知。

必须 允许用户可以在网络请求时,配置重试的逻辑,并且重试的间隔应该以指数形式递增,直至一个最大的默认重试间隔,以使用户可以简单地处理网络抖动问题。

错误处理

目标:将 SDK 运行时生命周期所涉及的一切异常,都合理地分组,降低用户的使用成本

架构约束

必须 至少明确区分出客户端错误和其它错误,以避免对客户端错误进行重试。

必须 允许客户可以明确识别并处理服务端的业务异常,以使用户能够针对具体的业务进行处理。

应该 提供一组默认的错误分类,建议的分类如下所示:

  • 客户端参数错误
  • 客户端未定义异常
  • 网络异常
  • 服务端业务异常
  • 服务端未定义异常

可观测性

目标:SDK 应提供日志(Logging)、链路追踪(Tracing)相关的能力,以使故障发生时,云服务提供商可以迅速定位和诊断到根因。

架构约束

必须 提供日志打印模块和默认日志,并在默认日志中打印出请求的唯一标识(UCloud Request ID),以便于快速唯一定位到具体请求。

必须 在请求信息的 User-Agent 中,标记 SDK 及所属编程语言的信息,云服务提供商将用以识别客户端版本存量,优化用户体验。

必须 允许用户自定义日志的输出、格式,以及主动关闭日志,以使用户可以完全掌控 SDK 的可观测性能力。

应该 在默认日志中隐藏机密信息,如签名、公钥等,保护用户用云安全的同时,防止 API 重放攻击。

测试

目标:SDK 作为在客户端运行的开发工具,无法在发布后回滚版本,因此具有严格的测试准入能力。

架构约束

必须 确保 100% 的单元测试覆盖率,确保 SDK 核心包能够得到完整的静态测试覆盖。

必须 采用某一持续集成服务,在 SDK 交付前,自动化地执行单元测试,并确保该测试通过。

不应该 编写面向服务包的测试代码,因为服务包应该由 API 契约自动生成,且 API 契约本身应由云服务提供商内部的测试能力确保 100% 的字段覆盖率。

技术写作

必须 在文档中心为每一个语言的 SDK 添加中文文档,其中包括 SDK 的基本使用方法。

必须 在 Github SDK 仓库添加英文 README、描述信息,并将其链接到文档中心主页。

必须 在 Github 中提供基于场景的代码示例,至少应包含一个 two-tier 示例,示例应使用全局配置,以使用户一次配置,即可运行全部场景示例。

开源治理

必须 在 Github 仓库放置 LICENSE 文件,并设置为 APL 2.0。

必须 为 SDK 工具设置一个社区维护状态,使用户对于该项目可以有一个合理的预期。维护状态列表详见开发者工具社区门户,并按照预设的最大响应时间对用户问题进行答复。

应该 在 Github 仓库的 .github 文件夹中放置开源贡献模版,为开源社区贡献者,提供默认的 Issue 和 Pull Request 模版,模版内容请参考 模版参考示例

服务集成

必须 将 SDK 最终产物投递至官方制品中央仓库(如果所用的语言存在中央制品仓)。

应该 至少集成一个代码风格检查服务,如 SonarCloud、Codacy。

应该 至少集成一个 CI 服务,如 Github Actions、Travis CI、Circle CI。

应该 至少集成一个安全检查服务,如 dependbot(UCloud 开源项目已默认集成)。

应该 集成 CLA 服务。

实现

配置选项

应该 提供以下配置选项(其它配置请参考 UCloud 配置公约):

配置 类型 描述
Region str (必填)服务所在地域,可参考 地域和可用区列表
ProjectId str (选填)项目的唯一标识,用于组织资源,大多数资源都需要 ProjectId,如果是主账号或财务账号,默认值为默认 ProjectId,如果是子账号非财务账号,则该字段必须填写。
BaseUrl str (选填)API 服务的访问端点,默认是 https://api.ucloud.cn
UserAgent str (选填)UserAgent 是 SDK 客户端特有的属性,用于区分使用 SDK 的版本。User-Agent 的定义请参考 MDN。用户自定义的 UserAgent 将追加到 SDK 版本号的末尾。例如, “MyAPP/0.10.1” -> “Python/3.7.0 Python-SDK/0.1.0 MyAPP/0.10.1”
Timeout int (选填)请求超时时间,默认 30s
MaxRetries int (选填)最大重试次数. 默认重试 3 次。设置该值大于 0 将对网络和服务可用性问题进行自动重试,使用指数退避的重试间隔,并自动跳过资源创建类的接口。
LogLevel int (选填)日志级别,可参考 ucloud/log 的级别定义,默认是 INFO

特性表

目标:

  1. 我们所有语言 SDK 都将按照该特性表进行对齐。
  2. 并非所有特性都会进入特性表,我们仅向特性表中添加必要的特性。
  3. 新特性的增加将尽可能地采取谨慎策略,避免因随意增加特性而引起的质量滑坡。
特性分类 特性 详情
请求 类型系统 支持校验类型和参数存在性
参数编码 支持将语言原生的对象模型,序列化为 .N 风格的请求参数
错误处理 支持将错误分类,并包装为语言原生的异常机制抛出
网络传输 支持对网络传输过程进行面向切面编程,并支持重试和自定义的 Transport 机制
中间件 日志 支持默认的终端日志打印,以及自定义日志配置
鉴权 支持对请求自动签名
测试 单元测试 支持在 SDK 交付前,进行 100% 的单元测试覆盖
文档 文档中心 支持在文档中心,撰写独立的文档仓库,引导用户使用
代码示例 支持至少 1 个场景的代码示例,如 Two-Tier

UCloud 配置公约

UCloud SDK 和 CLI 两个大类的开发工具将共享一系列的全局配置,以使用户在仅需配置一次的前提下,可以使用全部的开发工具。

必须 使所有工具共享以下的环境变量:

  • UCLOUD_PUBLIC_KEY
  • UCLOUD_PRIVATE_KEY
  • UCLOUD_BASE_URL

应该 使工具可以读取以下的配置文件。

  • ~/.ucloud/credential.json

文件内容示例如下:

{"public_key":"...","private_key":"..."}