作為一個云原生的開發(fā)者,你會最關(guān)注哪方面的開發(fā)體驗?在你的應(yīng)用中與云上的資源進(jìn)行交互肯定是你非常在意的吧,不管是往Service Bus中發(fā)送一條消息,亦或是為更大的運(yùn)算需求創(chuàng)建新的虛擬機(jī)。你可以利用云平臺的SDK,比如Azure SDK來完成所有這些操作,那么Azure SDK是如何寫出來的呢?一個云平臺的SDK和一個傳統(tǒng)的SDK有何區(qū)別?
傳統(tǒng)SDK和云平臺SDK之間的不同
傳統(tǒng)SDK,比如說.NET SDK或者JAVA SDK,都是.NET運(yùn)行時(.NET CLR)或者JAVA運(yùn)行時(JVM)的編程接口,他們之間的“通訊協(xié)議”是在進(jìn)程內(nèi)的,基于二進(jìn)制的。
云平臺SDK通?;贠penAPI定義。OpenAPI更像是一個跨進(jìn)程的基于RESTFul HTTP APIs的通訊協(xié)議,OpenAPI云計算的世界中無處不在,但是OpenAPI有其自己的局限性。
利用OpenAPI和Azure進(jìn)行交互時候會遇到的問題
OpenAPI是一個REST API Service的接口定義,對于任何一個程序語言來說,他都不是一個開箱即用的解決方案。當(dāng)一個開發(fā)者想要開始使用OpenAPI,他通常會遇到下面的一些問題:
·異常處理
·長時間運(yùn)行操作的處理
·分頁操作處理
·HTTP Client生命周期管理
為這些處理構(gòu)建健壯的代碼并不是一件容易的事情。這種情況下,引入SDK就變成了一種很自然地選擇。
微軟是如何從OpenAPI中生成Azure SDK的
Azure SDK的設(shè)計遵從了通用SDK庫設(shè)計指導(dǎo),這份指導(dǎo)綱要確保了在不同Azure Service之間一致的SDK使用體驗,從2022年3月31號開始,我們對不符合指導(dǎo)綱要版本的SDK庫開始了逐步淘汰。
為一個新的Azure Service創(chuàng)建SDK,Azure SDK團(tuán)隊緊密合作,常見的工作步驟如下:
1.Azure Service團(tuán)隊定義好OpenAPI說明(Swagger file),并且在REST API specification repository起一個PR。
2.Azure SDK團(tuán)隊會審核新的OpenAPI說明,確保里面沒有破壞性變更,語法錯誤等等。
3.Azure SDK團(tuán)隊利用AutoRest從OpenAPI說明當(dāng)中生成客戶端庫。AutoRest是微軟創(chuàng)建的一個開源客戶端庫生成工具來訪問Restful web services.AutoRest利用不同語言的拓展來為不同編程語言生成Restful web service的客戶端庫。
4.我們會審核生成出來的客戶端庫,并起一個PR到相應(yīng)語言SDK的Github repository.我們有一個非常棒的內(nèi)部工程平臺對這些客戶端庫進(jìn)行測試,以確保我們不會引入任何regression issue。這些測試包括自動生成的測試和手寫測試,但是在未來我們會更多的依賴自動生成的測試用例。
5.一旦所有檢查都通過了,這個新生成的客戶端庫就會被合并到相應(yīng)語言的SDK Github Repository。
6.在客戶端庫被合并到相應(yīng)語言的SDK Github repository之后,相應(yīng)的持續(xù)集成和部署管線就會被觸發(fā),如果一切無誤,新的客戶端庫就會被發(fā)布到相應(yīng)語言的包管理器,如nuget,npm等等。
7.所有SDK相關(guān)文檔,樣例代碼也會陸續(xù)得到更新。
AutoRest是整個客戶端庫生成過程當(dāng)中的關(guān)鍵。AutoRest知道常見模式的REST API調(diào)用,并在客戶端庫中將這些調(diào)用暴露成對于開發(fā)者友好的編程接口。比如說,長時間運(yùn)行的操作(Long-running operation,LRO)以及一些資源創(chuàng)建,刪除等無法立即知道操作結(jié)果的REST API調(diào)用。這些情況下,服務(wù)器會返回一個201(Created)或者202(Accepted)狀態(tài)碼,并附帶一個鏈接來持續(xù)監(jiān)測請求的完成狀態(tài)。這個操作行為對于直接的RESTFul API調(diào)用是合理的,但是從編程語言的角度來看這是有問題的,這種操作應(yīng)該被轉(zhuǎn)變成一個帶回調(diào)函數(shù)的異步操作,回調(diào)函數(shù)允許開發(fā)者為LRO操作的成功或失敗編寫相應(yīng)代碼。OpenAPI,很不幸的,沒有這種異步語法上的支持。為了能夠支持這種操作,微軟定義了一系列AutoRest OpenAPI拓展來豐富OpenAPI的語法。
現(xiàn)在讓我們回到之前的LRO場景。我們可以在OpenAPI中定義一個x-ms-long-running-operation。比如說,下面的定義是一個創(chuàng)建/更新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方法調(diào)用就變成了下面的樣子,以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的基礎(chǔ)架構(gòu),比如說HTTP Client的生命周期管理,異常處理。利用Azure Core,我們就可以在OpenAPI中定義更多的拓展,并將這些拓展轉(zhuǎn)變成更加開發(fā)者友好的客戶端庫語法,常見的OpenAPI拓展有:
·X-ms-error-response:該拓展可以確定是否把一些http返回狀態(tài)碼映射成為一個錯誤
·X-ms-pageable:該拓展可以將返回的list映射成為一個可分頁的結(jié)果
更多的拓展,請參見AutoRest Extensions for OpenAPI
通用SDK庫設(shè)計指導(dǎo):
https://azure.github.io/azure-sdk/general_introduction.html
REST API specification repository:
https://github.com/Azure/azure-rest-api-specs
AutoRest:
https://github.com/Azure/AutoRest
AutoRest OpenAPI拓展:
https://github.com/Azure/autorest/tree/main/docs/extensions
完整定義在這里:
https://github.com/Azure/azure-rest-api-specs/blob/d48ca7ed92cbb4f972eb6214bdb3200edaf78369/specification/compute/resource-manager/Microsoft.Compute/stable/2021-11-01/compute.json#L3624
完整代碼在這里:
https://github.com/Azure-Samples/azure-sdk-for-go-samples/blob/e42648befd65a0b92ae55f92912f3ba91a771dec/sdk/resourcemanager/compute/createVM/main.go#L528
Azure Core:
https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/azcore
AutoRest Extensions for OpenAPI:
https://github.com/Azure/autorest/tree/main/docs/extensions
我們討論了使用云SDK的好處以及微軟構(gòu)建云SDK的流程,感謝您的閱讀。