作为一个云原生的开发者,你会最关注哪方面的开发体验?在你的利用中与云上的资源进行交互必定是你十分在意的吧,不论是往 Service Bus 中发送一条音讯,亦或是为更大的运算需要创立新的虚拟机。你能够利用云平台的 SDK,比方 Azure SDK 来实现所有这些操作,那么 Azure SDK 是如何写进去的呢?一个云平台的 SDK 和一个传统的 SDK 有何区别?
传统 SDK 和云平台 SDK 之间的不同
传统 SDK,比如说.NET SDK 或者 JAVA SDK,都是.NET 运行时(.NET CLR)或者 JAVA 运行时(JVM)的编程接口,他们之间的“通信协定”是在过程内的,基于二进制的。
云平台 SDK 通常基于 OpenAPI 定义。OpenAPI 更像是一个跨过程的基于 RESTFul HTTP APIs 的通信协定,OpenAPI 云计算的世界中无处不在,然而 OpenAPI 有其本人的局限性。
利用 OpenAPI 和 Azure 进行交互时候会遇到的问题
OpenAPI 是一个 REST API Service 的接口定义,对于任何一个程序语言来说,他都不是一个开箱即用的解决方案。当一个开发者想要开始应用 OpenAPI, 他通常会遇到上面的一些问题:
- 异样解决
- 长时间运行操作的解决
- 分页操作解决
- HTTP Client 生命周期治理
为这些解决构建强壮的代码并不是一件容易的事件。这种状况下,引入 SDK 就变成了一种很天然地抉择。
微软是如何从 OpenAPI 中生成 Azure SDK 的
Azure SDK 的设计听从了通用 SDK 库设计领导,这份领导大纲确保了在不同 Azure Service 之间统一的 SDK 应用体验,从 2022 年 3 月 31 号开始,咱们对不合乎领导大纲版本的 SDK 库开始了逐渐淘汰。
为一个新的 Azure Service 创立 SDK,Azure SDK 团队严密单干,常见的工作步骤如下:
- Azure Service 团队定义好 OpenAPI 阐明(Swagger file),并且在 REST API specification repository 起一个 PR。
- Azure SDK 团队会审核新的 OpenAPI 阐明,确保外面没有破坏性变更,语法错误等等。
- Azure SDK 团队利用 AutoRest 从 OpenAPI 阐明当中生成客户端库。AutoRest 是微软创立的一个开源客户端库生成工具来拜访 Restful web services. AutoRest 利用不同语言的拓展来为不同编程语言生成 Restful web service 的客户端库。
- 咱们会审核生成进去的客户端库,并起一个 PR 到相应语言 SDK 的 Github repository. 咱们有一个十分棒的外部工程平台对这些客户端库进行测试,以确保咱们不会引入任何 regression issue。这些测试包含主动生成的测试和手写测试,然而在将来咱们会更多的依赖主动生成的测试用例。
- 一旦所有查看都通过了,这个新生成的客户端库就会被合并到相应语言的 SDK Github Repository。
- 在客户端库被合并到相应语言的 SDK Github repository 之后,相应的继续集成和部署管线就会被触发,如果所有无误,新的客户端库就会被公布到相应语言的包管理器,如 nuget, npm 等等。
- 所有 SDK 相干文档,样例代码也会陆续失去更新。
AutoRest 是整个客户端库生成过程当中的要害。AutoRest 晓得常见模式的 REST API 调用,并在客户端库中将这些调用裸露成对于开发者敌对的编程接口。比如说,长时间运行的操作(Long-running operation, LRO)以及一些资源创立,删除等无奈立刻晓得操作后果的 REST API 调用。这些状况下,服务器会返回一个 201(Created)或者 202(Accepted)状态码,并附带一个链接来继续监测申请的实现状态。这个操作行为对于间接的 RESTFul API 调用是正当的,然而从编程语言的角度来看这是有问题的,这种操作应该被转变成一个带回调函数的异步操作,回调函数容许开发者为 LRO 操作的胜利或失败编写相应代码。OpenAPI, 很可怜的,没有这种异步语法上的反对。为了可能反对这种操作,微软定义了一系列 AutoRest OpenAPI 拓展来丰盛 OpenAPI 的语法。
当初让咱们回到之前的 LRO 场景。咱们能够在 OpenAPI 中定义一个 x -ms-long-running-operation。比如说,上面的定义是一个创立 / 更新 Azure VM 的 OpenAPI 定义(残缺定义可在这里找到)
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}": {
"put": {
"tags": ["VirtualMachines"],
"operationId": "VirtualMachines_CreateOrUpdate",
"description": "The operation to create or update a virtual machine. Please note some properties can be set only during virtual machine creation.",
"parameters": [
{
"name": "resourceGroupName",
"in": "path",
"required": true,
"type": "string",
"description": "The name of the resource group."
},
{
"name": "vmName",
"in": "path",
"required": true,
"type": "string",
"description": "The name of the virtual machine."
},
{
"name": "parameters",
"in": "body",
"required": true,
"schema": {"$ref": "#/definitions/VirtualMachine"},
"description": "Parameters supplied to the Create Virtual Machine operation."
},
{"$ref": "#/parameters/ApiVersionParameter"},
{"$ref": "#/parameters/SubscriptionIdParameter"}
],
"responses": {
"200": {
"description": "OK",
"schema": {"$ref": "#/definitions/VirtualMachine"}
},
"201": {
"description": "Created",
"schema": {"$ref": "#/definitions/VirtualMachine"}
},
"default": {
"description": "Error response describing why the operation failed.",
"schema": {"$ref": "#/definitions/CloudError"}
}
},
"x-ms-long-running-operation": true
}
}
有了下面的 OpenAPI 定义,咱们生成的客户端库中的 BeginCreateOrUpdate 办法调用就变成了上面的样子,以 Go 语言为例(残缺代码可在这里找到)
pollerResponse, err := vmClient.BeginCreateOrUpdate(ctx, resourceGroupName, vmName, parameters, nil)
if err != nil {return nil, err}
resp, err := pollerResponse.PollUntilDone(ctx, 10*time.Second)
if err != nil {return nil, err}
}
上述代码中的 Poller 类来自于 Azure Core 我的项目。Azure Core 提供了整个 Azure SDK 的基础架构,比如说 HTTP Client 的生命周期治理,异样解决。利用 Azure Core, 咱们就能够在 OpenAPI 中定义更多的拓展,并将这些拓展转变成更加开发者敌对的客户端库语法,常见的 OpenAPI 拓展有:
- X-ms-error-response:该拓展能够确定是否把一些 http 返回状态码映射成为一个谬误
- X-ms-pageable:该拓展能够将返回的 list 映射成为一个可分页的后果
更多的拓展,请参见 AutoRest Extensions for OpenAPI
咱们探讨了应用云 SDK 的益处以及微软构建云 SDK 的流程,感谢您的浏览。
长按辨认二维码
关注微软中国 MSDN