作为一个云原生的开发者,你会最关注哪方面的开发体验?在你的利用中与云上的资源进行交互必定是你十分在意的吧,不论是往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团队严密单干,常见的工作步骤如下:

  1. Azure Service团队定义好OpenAPI阐明(Swagger file),并且在REST API specification repository起一个PR。
  2. Azure SDK 团队会审核新的OpenAPI阐明,确保外面没有破坏性变更,语法错误等等。
  3. Azure SDK 团队利用AutoRest从OpenAPI阐明当中生成客户端库。AutoRest是微软创立的一个开源客户端库生成工具来拜访Restful web services. AutoRest利用不同语言的拓展来为不同编程语言生成Restful web service的客户端库。
  4. 咱们会审核生成进去的客户端库,并起一个PR到相应语言SDK的Github repository. 咱们有一个十分棒的外部工程平台对这些客户端库进行测试,以确保咱们不会引入任何regression issue。这些测试包含主动生成的测试和手写测试,然而在将来咱们会更多的依赖主动生成的测试用例。
  5. 一旦所有查看都通过了,这个新生成的客户端库就会被合并到相应语言的SDK Github Repository。
  6. 在客户端库被合并到相应语言的SDK Github repository之后,相应的继续集成和部署管线就会被触发,如果所有无误,新的客户端库就会被公布到相应语言的包管理器,如nuget, npm等等。
  7. 所有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