揭开云的面纱,从云的语言OpenAPI开始

阿里云作为国内乃至亚洲领先的IaaS云厂商,提供了丰富的算力产品服务,以算力商品在线化的方式进行出售。当前阶段算力商品的载体形态主要是实例规格。那么,购买实例规格的OpenAPI (如RunInstances)也就最具IaaS云的代表性。那么,分析RunInstances接口(编程协议)也就最具典型性。

 

下面以阿里云OpenAPI RunInstances参数定义,进行‘语言’特性分析。

https://help.aliyun.com/document_detail/63440.html

 

语言的基本特性来解读OpenAPI

OpenAPI指向性

指向性通知表示明确地表达、描述一个概念、实体、行动等。对于API指向性,意味着API的含义或者功能应首先避免二义性。

我们选择RunInstances作为分析案例,那么它指向什么? 开启实例(Run),也就是云上购买一批实例(Instance等价一定规模的算力)。从实例概念来说,RunInstance指向很明确:购买并启动实例。

进一步分析实例之所以成为实例,且能区分其他实例,那么实例应该具备更具体的‘区分性’的指向性。实例提供算力服务,由此实例的具体指向就是算力相关的具体指向。我们知道实例的算力体现:计算、存储、网络三大件,以及安全等核心要素。所以,RunInstances 里面预期应该有这些算力相关的具体指向。那么RunInstances 当前实际参数在这些具体指向性是怎么体现的呢?

 

OpenAPI计算指向性

参照RunInstances API 定义,其中有如下参数,这些参数对计算进行了‘指向’。

参数名称

数据类型

取值样例

InstanceType

String

ecs.g6.large

InstanceName

String

k8s-node-[1,4]-alibabacloud

CpuOptions.Core

Integer

2

CpuOptions.ThreadsPerCore

Integer

2

CpuOptions.Numa

String

1


OpenAPI存储指向性

参照RunInstances API 定义,其中有如下参数,这些参数体现了对存储‘指向’性。

参数名称

数据类型

取值样例

SystemDisk.Size

String

40

SystemDisk.Category

String

cloud_ssd

SystemDisk.DiskName

String

cloud_ssdSystem

SystemDisk.Description

String

SystemDisk_Description

SystemDisk.PerformanceLevel

String

PL0

SystemDisk.AutoSnapshotPolicyId

String

sp-bp67acfmxazb4p****

IoOptimized

String

optimized

StorageSetId

String

ss-bp67acfmxazb4p****

StorageSetPartitionNumber

Integer

2

DataDisk.N.PerformanceLevel

String

PL1

DataDisk.N.AutoSnapshotPolicyId

String

sp-bp67acfmxazb4p****

DataDisk.N.Encrypted

String

false

DataDisk.N.Description

String

DataDisk_Description

DataDisk.N.SnapshotId

String

s-bp17441ohwka0yuh****

DataDisk.N.Device

String

null

DataDisk.N.Size

Integer

2000

DataDisk.N.DiskName

String

cloud_ssdData

DataDisk.N.Category

String

cloud_ssd

DataDisk.N.DeleteWithInstance

Boolean

true

DataDisk.N.KMSKeyId

String

0e478b7a-4262-4802-b8cb-00d3fb40****

 

OpenAPI网络指向性

参照RunInstances API 定义,其中有如下参数,这些参数体现了对网络‘指向’性。

参数名称

数据类型

取值样例

VSwitchId

String

vsw-bp1s5fnvk4gn2tws0****

InternetMaxBandwidthIn

Integer

10

InternetMaxBandwidthOut

Integer

10

Ipv6AddressCount

Integer

1

NetworkInterfaceQueueNumber

Integer

8

NetworkInterface.N.VSwitchId

String

vsw-bp67acfmxazb4p****

NetworkInterface.N.NetworkInterfaceName

String

Network_Name

NetworkInterface.N.Description

String

Network_Description

NetworkInterface.N.SecurityGroupId

String

sg-bp67acfmxazb4p****

NetworkInterface.N.PrimaryIpAddress

String

172.16.**.**

NetworkInterface.N.QueueNumber

Integer

8

NetworkInterface.N.SecurityGroupIds.N

RepeatList

sg-bp15ed6xe1yxeycg7****

PrivateIpAddress

String

10.1.**.**

Ipv6Address.N

RepeatList

Ipv6Address.1=2001:db8:1234:1a00::***


OpenAPI安全指向性

参照RunInstances API 定义,其中有如下参数,这些参数体现了对网络‘指向’性。

参数名称

数据类型

取值样例

SecurityGroupId

String

sg-bp15ed6xe1yxeycg7****

Password

String

EcsV587!

PasswordInherit

Boolean

false

RamRoleName

String

RAM_Name

SecurityGroupIds.N

RepeatList

sg-bp15ed6xe1yxeycg7****

SecurityOptions.TrustedSystemMode

String

vTPM

SecurityOptions.ConfidentialComputingMode

String

Enclave

小结

  1. 分析RunInstances 不难发现,里面还有其他的指向性属性参数,这里就不一一解说。
  2. 计算、存储、网络、安全等这些参数有的是必须,有的非必需。非必需的都有默认值。例如InstanceType必须的,InstanceName非必须的。
  3. 这些参数有的是基本属性,有的是高级属性。例如CpuOptions.Numa计算的高级特性,SecurityGroupIds.N基本安全组,SecurityOptions.TrustedSystemMode安全增强。
  4. 计算、存储、网络、安全等构成具体的指向,并且这些具体指向因为各种组合关系,使得这种指向丰富度大大增强,也导致真正理解具体商品对应的明细指向,有一定的成本。也间接反应了面向实例规格这种商品购买,具有一定的学习门槛。
  5. 如果继续存在InstanceType 这周云产品售卖形态,意味着满足指向型的RunInstances的各具体指向只会更加复杂、更加多元。目前通过启动模版、授权购买的方式可以简化一些操作,本质并没有‘单纯面向概念’,例如实例规格进行交互。
  6. 未来超越当前的指向有哪些可能。
    1. 一种可能的超越方式:例如安全是默认配置项,安全的相关配置按默认处理,那么请求参数里面可以省去这部分。
    2. 一种可能是新的实例规格出售,面向一个算力场景,例如云桌面,其背后具体什么样的资源交付形态,用户不感知,用户只需感知云桌面本身的特性。
    3. 新的产品规格实例在某个产品代上就终止了,改为‘属性、品牌’。老旧代实例被新的替代。这意味着:新的实例规格价格完全碾压旧代实例,新的实例规格各方面性能都具备很强的能力,完全可以适应各种场景需求
    4. 面向算力或者服务的交付,屏蔽硬件、软件的差异


OpenAPI 描述性

描述性意味着:对象具有灵活性,支持多种场景的需求,描述性用于更好理解。

描述性这里狭义地理解对当前实例规格的描述说明,算一个辅助的介绍。

参照RunInstances API 定义, 可以将以下参数理解为描述性的内容。

RegionId

String

cn-hangzhou

ZoneId

String

cn-hangzhou-g

InstanceName

String

k8s-node-[1,4]-alibabacloud

Description

String

Instance_Description

这些参数就是典型的针对具体指向的描述性参数。

整个RunInstances本身就是在描述云上购买算力商品这么一种‘编程协议行为’。

 

OpenAPI 逻辑性

逻辑性本质是按一定规则、条理来表达一种含义。参照RunInstances API 定义,下面的这几个参数可以说是逻辑性的典型代表。

参数名称

数据类型

必填性

取值样例

LaunchTemplateId

String

lt-bp1apo0bbbkuy0rj****

LaunchTemplateName

String

LaunchTemplate_Name

LaunchTemplateVersion

Long

3

1.

当前云上商品形态主流的还是‘服务器’这个具体实物形态,对应RunInstances的逻辑就是实现这一形态,支持购买生产一台服务器的需要的各个逻辑参数、支持可编程化。几乎任意一个API本身就是一种逻辑的表现。

 

OpenAPI 交际性

交际性通常是互动的方式进行,要求互动的双方相互听的懂、相互有响应。

对应RunInstances的交际性,意味着:RunInstance输入参数应该支持

  1. 服务端应该及时有响应
    1. 交际如果只是单向的,这个互动是没有‘灵魂’的。对于云的API交际性的典型体现:接口响应要及时,否则就阻碍了高效互动。
    2. 相应应该和请求是关联的,要求输出相关结果。
  1. 互动的响应,有积极的、消极的
    1. 接口反馈有正确的、不正确的。对应接口结果,有成功的反馈,失败的反馈,并且失败有具体的原因、错误表达,便于下一轮的互动,这种结果应该符合互动的上下文、互动双方能够理解。
  1. 可以反复进行

 阿里云的RunInstances的服务响应、结果输出都有相关明确的定义,很好地体现了语言的’交际性‘

 

OpenAPI 传播性

一种语言的传播性意味着:语言交流的人群规模、人群使用的频率。我们知道中文和英文在形成上是有很大的不同的,例如:语言文字的结构、语法、文法、句法的差异。追根溯源,本质是文化的差异。


那么OpenAPI的传播性,同样意味着有多少人使用,使用频率如何。前面说到RunInstance是阿里云当前商品售卖形态的主要代表,自然RunInstances是高频使用的。而人群规模也就是云的用户规模。对比AWS、AliYun的接口,

 

OpenAPI 名族性

在这里对应云平台自身的特性。例如阿里云的RunInstances、华为的RunInstance、腾讯的RunInstance、AWS的RunInstance 具有各自平台的特性。没有好坏之分,只有合适与否的选择。

 

语言的创新和实践

OpenAPI作为云的语言,作为一种用户与云,端与云的交互、互动的程序协议。那么创新性、实践性尤为关键。


OpenAPI 创造性

对于接口协议,从使用方来说,一经定义,就不期望随意修改。越简单越好,越是见名知意的表述越友好。从定义方来说,要能够支持明确的语意,要能在一套接口协议上支持各种场景的需求,要能提供易用性同时支持灵活性。


参照RunInstances API 定义,不能发现其中 Tag的定义,就很好的‘创造性’体现。通过Tag用户自定义自己的名词的Key、Value,这些Key、Value可以实现财务、资源、管理的自定义处理,打开了‘On Cloud’的各种可能的‘二次处理’的大门。例如基于Tag的分账,例如基于Tag的资源和应用分组关心管理,例如给予Tag的私有池匹配调度等。

Tag.N.Key

String

TestKey

Tag.N.Value

String

TestValue

 

OpenAPI 结构性

任何语言都有其相关的基本词汇、词法、句法等结构性信息。OpenAPI作为云的语言,顺着这个思路来看,那么云的所有OpenAPI构成了云的语言,所有OpenAPI遵循一个统一的词汇、词法、句法规则。


对应RunInstances(看作一个句子),它的句法结构性,例如计算、存储、网络、安全、基本描述等。它的词法结构性,单一概念指向的共同前缀结构性。例如SystemDisk SecurityOptions等。

 

云应该具备很强的实践性,否则云很难实现普惠。我们说云提供的是‘可编程基础设施‘,这个基础实施对外的沟通语言是OpenAPI,OpenAPI是提供算力服务的,被集成到业务的代码中。哪些因素会影响这种实践性的‘质量’或者‘生命力’?回到词汇、词法、句法,对应具体接口,也就是接口的数据结构、接口的功能边界、接口之间的链接。


目前看,OpenAPI的结构性AWS做的非常好,阿里云还有欠缺,为什么这么说。

  1. 形式上,AWS 明确的列举了它的平台上它提供的OpenAPI Data types,并且各接口严格遵守和使用这些Data types。看起来很简单的形式,其实意味着:各个新的产品推出、服务接口的定义,首先要在整体云的data types里面进行比较,是否已有相关data types,新的data types 是否合乎规范。纵观阿里云,并没有这样的data types 的目录,这也就不难发现,为何阿里云的一些接口定义里面出现了相同概念的多种参数命名。例如RunInstances的RegionId,DescribeSavingsPlansCoverageDetail https://help.aliyun.com/document_detail/298067.html 中的返回对象是Region


例如

PurchaseReservedInstancesOffering

https://help.aliyun.com/document_detail/100032.html

 

参数名

参数类型

默认值

取值说明

OfferingType

String

All Upfront

预留实例券的付款类型。取值范围:

  • No Upfront:零预付
  • Partial Upfront:部分预付
  • All Upfront(默认):全预付

 

QuerySavingsPlansInstance

https://help.aliyun.com/document_detail/198100.html


参数名

参数类型

默认值

取值说明

PayMode

String

total

付款类型:

  • total 全预付
  • half 半预付
  • zero 0预付

 

  1. 我们说AWS的产品之间的互通性很强,阿里云的产品之间很难一步到位。这什么意思呢。例如你在阿里云购买了ECS、然后购买阿里云的RDS,然后期望ECS和RDS很easy的打通一起服务。在AWS上这块的相对简便些。https://zhuanlan.zhihu.com/p/24721353

https://docs.aws.amazon.com/codecommit/latest/userguide/integrations.html


当然从另外一个“狡辩”角度可以说,阿里云的发展规模还没有达到aws的规模,所以服务还不够成熟,或者说API还不够成熟。从设计视角看,阿里云在API当前的设计上存在的结构性缺陷。

 揭开云的面纱,从云的语言OpenAPI开始

 

OpenAPI 具体

具体性本质是原子性的另外一种说法。这里其实有一个很模糊的边界,究竟什么概念或者实体范围算一个原子呢,到底切多谢比较合适呢?


例如存储接口的定义,从read、 write 的参数,哪一个粒度最合适,是byte、byte[]、string、object?


例如tags.Key、value 这里是普通string,还是jsong string、还是其他自定义string 甚至加密string,那种合适?


具体性作者的经验是:定义OpenAPI的时候,尽量从属性原子开始定义、到接口功能原子定义结束,从‘概念实体‘具体化设计,到不同角色同学评审一致结束。


OpenAPI 准确

准确性一种是本接口内部的准确性,一种是接口体系内的准确性。准确性第一直观体现在接口命名上。例如create、delete、query,get、put、post、move等关键动词的定义,以及instance、vpc、securityGroup等名词的定义。


例如取消、释放、删除,究竟是delete、cancel、release这样的动词,还是统一delete呢?


准确性作者的经验是:应该首先遵循整体API的上下文环境(可能之前采取了某种风格,这种风格存在缺陷,不建议引入新的风格。因为新的又增加了用户的学习成本),在这个环境下,努力做到准确(很难说有绝对的准确,可能在这个场景下很准确,在另外一个环境下,可能就存在歧义了)。单个接口的准确性应该努力做到极致的‘合理’。多个接口之间的准确性,依赖工具的统一检测和管理、参照业界通用的做法


OpenAPI 简练

简练首先要做到一个接口只做一件事情。如果一个接口做多个事情,那么这个接口相比一件事就不够简练了。

 

小结

不论以什么方式来看云的OpenAPI,不论以什么设计准则来设计和实施云的OpenAPI,本质的不会变:做到简单、易用、可靠。回到接口设计本身的技术经验,业界有很多成熟的经验可以拿来学习(不一定能直接照搬到工作中,可能有一些技术债务不允许做优化----优化可能又引入新的 不一致)

下面列举Google、Aws、Azure的接口设计实践文档,这些文档还是满值得反复学习、借鉴的。

https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design

https://docs.microsoft.com/en-us/azure/architecture/microservices/design/api-design

 

https://aws.amazon.com/startups/start-building/how-to-build-a-public-facing-API/

https://aws.amazon.com/api-gateway/api-management/

 

https://cloud.google.com/blog/products/api-management/google-cloud-api-design-tips

https://developers.google.com/google-ads/api/rest/design/overview

https://cloud.google.com/apis/design/

 

总结

如何学习API设计,特别是云的API设计,从购买创建实例RunInstances开始吧。

实施好单个API、以及和生态整体API的协调一致,可以借鉴语言的基本特性来反问自己,是否可以进一步优化下?

最终总有一些坑,一些前人的经验教训可以提前学习,提前规避掉,那么业务的API设计文档,值得反复学习

上一篇:Java笔试题考点梳理


下一篇:新书自荐《深入集群:大型数据中心资源调度与管理》