简介:由于每个网关所对应的后端情况不同,因此没有一套元数据可以适用于所有的网关。阿里云通过重新定义一门 DSL 语言 —— Darabonba 来支持不同风格的 OpenAPI,同时支持多语言的 SDK、Code Sample 目标生成。本文将从技术原理和解决方案分享相关的探索和实践。


如今 OpenAPI 已经成为完成系统之间集成的重要桥梁,OpenAPI 的可用性以及用户在使用时的体验就变得越来越重要,阿里云前架构师曾说过:"阿里云的本质是一家卖 API 的公司。API 有没有做好,是关乎生死的大事"。但是从日常来自用户的反馈中我们总结了以下比较通用的几点 OpenAPI 体验问题:

  • 云产品 OpenAPI 没有提供 SDK 或者 SDK 语言不全;
  • 部分云产品的 SDK 使用风格差异过大,导致使用成本增加;
  • API 文档缺失或者不够清晰,不具备指导意义;
  • 没有场景化 Code Sample 或提供 CodeSample 无法运行。

多语言 SDK 生成

说起生成多语言 SDK,大家第一时间想起的一定是当前业界内生成多语言 SDK 的通用方案——Swagger,开发者通过 Swagger 定义的 OpenAPI 标准并配合模板的方式来生成多语言 SDK。不过问题并没有因此而得到完美的解决。首先模版的生成方式相对生硬,虽然实现起来容易,但维护起来却不那么灵活;其次,大量 OpenAPI 并不是 RESTful 风格的,这就导致很多产品现存的 OpenAPI 在文档、SDK 等场景下,无法使用上 Swagger 这样强大的生态工具链。既然无法沿用 Swagger 规范元数据的方法来解决这个问题,我们就需要对我们的工作重新进行抽象。在笔者看来,之所以没有一套元数据可以适用于所有的网关主要还是因为每个网关所对应的后端情况不同,就像机器语言或者汇编语言会因为架构的不同而有所不同,但是其本质还是描述如何通过操作寄存器、内存里的数据来完成一个程序,高级语言就是通过 AST 兼容了各平台的这些不同最后解决了这些问题。而对于 OpenAPI 来说也是同样的道理,所以我们通过重新定义一门 DSL 语言 Darabonba 来描述各种各样的 OpenAPI。

通过 Darabonba 对 OpenAPI 进行描述,其本质就是统一了元数据,只是这个元数据并不是 JSON 或者 Yaml 这样的方式来描述的,而是通过 DSL 代码来描述。Darabonba 的编译器则会将 Darabonba 的 DSL 代码转化为 AST,通过 OpenAPI 描述转化而来的 AST 不仅包含了 OpenAPI 的信息,而且还包含整个 OpenAPI 的流程性描述,所以我们只需要通过 AST 开发对应的各语言SDK就可以生成多语言的 SDK了。Darabonba 具体的设计思路和理念可参考文章:Darabonba:支持任意 OpenAPI 网关的多语言 SDK 方案,这里就不再赘述。

模块化设计

在通过元数据向生成 SDK 的过程中,仅仅通过对 OpenAPI 的数据模型和请求/响应描述是不够的,还需要各种参数处理,签名生成,文件上传,流操作等各种复杂的方法,以往通过模板生成 SDK 的时会选择维护一个各语言的核心模块来封装这些方法,但是随着支持的 OpenAPI 越来越多核心库中的方法也是越来越多,就会产生以下的问题:

  • 客户使用或者开发者接入核心库的 SDK 开发者来说成本会越来越大;
  • 核心库的维护人员的维护成本也会越来越高,随着方法越来越多也需要不断的对核心库进行重构,遇到不兼容性改动的可能性也会越来越高;
  • 所有方法杂糅在一个核心库中,在修改时容易牵一发动全身,需要大量的测试用例保障。

在通过 Darabonba 生成的 SDK 时也会遇到同样的问题,Darabonba 作为一门 DSL 语言主要能力在于描述 OpenAPI ,为了保障生成的 SDK 具备完整的功能同样需要很多实现很多核心方法,而在总结以往维护核心库的中遇到的问题以后,我们选择了现在在高级语言中非常常见的模块化开发理念,并提供了相应的命令行工具 Darabonba CLI 和 Darabonba 模块仓库。

接口模块

Darabonba 其核心能力是描述 OpenAPI,缺少复杂逻辑实现的能力,为了弥补这个能力 Darabonba 设计了接口模块的概念。与 Java 中的 interface 接口类型定义类似,Darabonba 的接口模块即是只在 Darabonba 编写的DSL 代码中只定义方法体的集合而并不实现其具体逻辑,真正的逻辑则是由各语言分别实现。例如 Darabonba 中常用的 Console 模块:

/*** Console val with log level into stdout* @param val the printing string* @return void* @example \[LOG\] tea console example*/
static function log(val: string): void;

我们只需要在模块中申明模块包含 log 方法并描述它的出参入参即可,而各语言则通过自身语言的特性来实现该方法即可,其具体实现可参考 Console 模块源码。在编写好生成接口模块以后可以通过 Darabonba 提供的 Darabonba CLI 执行 dara publish 将模块发布到 Darabonba 模块仓库,就可以在 Darabonba 代码中使用了。下面就是我们通过引入 Console 模块来打印字符串的一段代码:

import Console;static async function main(args: [ string ]) throws : void {Console.log("hello world!");
}

通过接口模块的设计理念将以往核心库中的方法根据功能拆分成一个个包含了特定功能的基础模块,不仅使得生成的 SDK 更好用逻辑更清晰,同时也做到了足够的抽象避免很多在生成 SDK 过程中重复造轮子的工作。目前 Darabonba 官方提供了包含了常用方法的 Util 模块、文件上传所使用的 FileForm 以及 XML 模块等,同时开发者也可以编写与自己业务逻辑相关的接口模块并发布到 Darabonba 模块仓库。

OpenAPI 模块

在 Darabonba 的模块化设计中不止有接口模块,事实上每一个 Darabonba 的项目都是一个模块,所以基于一组 OpenAPI 描述编写的 Darabonba 代码就是一个 OpenAPI 模块。开发者在完成了 OpenAPI 描述的 Darabonba 代码编写以后,同样可以通过 Darabonba CLI 将描述 OpenAPI 的 Darabonba 模块发布到模块仓库中,这样使用 SDK 的用户就可以通过模块的详情页面查看 SDK 中包含的方法及各语言 SDK 的安装说明等信息了。

基于一组 OpenAPI 发布的 Darabonba 模块不仅可以帮助用户更好的了解这组 OpenAPI,更可以在这个基础上实现 OpenAPI 接口的 Code Sample 编写,进而实现多语言的 Code Sample 统一生成。

Code Sample 自动生成

可以说对于简单的 API 调用普通的 API 文档就足够了,但是随着现在 OpenAPI 在系统与系统集成之间使用的越来越广泛,其复杂度也随之提高,以往单纯使用 API 文档的方式已经不足以让客户顺利的使用 OpenAPI 了。从阿里云目前的工单情况来看,SDK 相关的客户咨询至少有一半是因为没有 Code Sample 造成的,其中更是有1/4的客户是直接要求为 SDK 提供 Code Sample。

这种情况下,能够提供给用户可运行、可调试的 Code Sample 示例就成了文档中必不可少的一部分,但是如何能够编写全语言的 Code Sample 并且保障其可运行,却是一个极大的问题。如果通过人力来维护,很容易就出现语言不全,或是编写的代码没有维护的问题,阿里云中遇到最多的问题就是 OpenAPI 在迭代,而 Code Sample 却忘记迭代了造成了提供出去的 Code Sample 无法使用从而被用户诟病。

通过引用模块仓库中 Darabonba 模块编写的 CodeSample 则可以避免这样的问题,首先多语言的自动生成,节约了大量的维护成本,而且风格统一利于用户理解;同时 Darabonba 编译时采用类型的强校验,一旦 OpenAPI 的参数或者返回结果出现了不兼容的更新,CodeSample 则会生成失败从而通知到开发者更新相关示例来解决这个问题。下面是阿里云语音服务 SDK 相关的 CodeSample 示例,大家也可以点击示例链接尝试生成:

import Dyvmsapi;
import RPC;
import Console;/*** 使用AK&SK初始化账号Client* @param accessKeyId* @param accessKeySecret* @param regionId* @return Client* @throws Exception*/
static function createClient (accessKeyId : string , accessKeySecret : string) throws : Dyvmsapi{var config = new RPC.Config{};// 您的AccessKey IDconfig.accessKeyId = accessKeyId;// 您的可用区IDconfig.accessKeySecret = accessKeySecret;return new Dyvmsapi(config);
}/*** @param args* @throws Exception*/
static async function main(args: [string]) throws : void {var client = createClient("accessKeyId","accessKeySecret");var request = new Dyvmsapi.QueryCallDetailByCallIdRequest{// 通话的唯一识别ID。callId = "100625930001^10019107xx",// 产品ID。// 11000000300006:语音通知。// 11010000138001:语音验证码。// 11000000300005:语音IVR。// 11000000300004:语音双呼。// 11000000300009:语音SIP。// 11030000180001:智能外呼。prodId = 11000000300004L,// 指定通话发生的时间,格式为Unix时间戳,单位毫秒。会查询这个时间点对应的一整天的记录。queryDate = 1577255564};var response = client.queryCallDetailByCallId(request);Console.log(response.code);
}

Test Cases 自动生成

在 OpenAPI 公布上线以后,如何能够保障 OpenAPI 持续可用就是一个非常重要的问题,如果没有一个保障机制,很可能会出现 OpenAPI 出了问题就无法及时发现,客户的投诉也就随之而来。而且 OpenAPI 和 SDK 也会遇到更新升级等情况,如何能保障这些更新升级不会给正在使用 OpenAPI 的客户造成问题也是 OpenAPI 提供方遇到的一个非常大的挑战。为了解决这些挑战, 就需要 OpenAPI 提供方编写 Test Cases 作为日常的持续集成来检验 OpenAPI 的可用性,但是目前多语言的 SDK 的 Test Cases 大多存在以下的问题:

  • 需要大量的人力去维护 Test Cases ,而且无法保障所有语言的 SDK 都拥有 Test Cases;
  • OpenAPI 的 Test Cases 少且更新频率低,造成了对 OpenAPI 的覆盖面低而无法起到有效的保障作用;
  • 各语言 SDK 的由各语言的开发同学分别维护,所以用例不同步导致不同语言之间的测试结果有所差异。

而Darabonba 的多语言生成能力则可以解决以上所有问题,只需要引用 SDK 在模块仓库中对应的 Darabonba 模块与 Darabonba 官方提供的断言模块 Assert 模块编写对应的 Darabonba Test Cases 即可为各语言 SDK 生成其对应的 Test Cases。通过 Darabonba 自动化生成 Test Cases 不仅可以解决人力不足 Test Cases 很难覆盖各语言 SDK 的情况,而且生成的各语言 Test Cases 标准一致,也可以解决各语言 Test Cases用例不同步造成的测试差异问题。下面是一段通过 Darabonba 编写的测试用例:

import Assert;
import Dyvmsapi;
import RPC;static function createClient (accessKeyId : string , accessKeySecret : string) throws : Dyvmsapi{var config = new RPC.Config{};config.accessKeyId = accessKeyId;config.accessKeySecret = accessKeySecret;return new Dyvmsapi(config);
}static async function TestNumberEqual() throws : void {
var client = createClient("accessKeyId","accessKeySecret");var request = new Dyvmsapi.QueryCallDetailByCallIdRequest{callId = "100625930001^10019107xx",prodId = 11000000300004L,queryDate = 1577255564};var response = client.queryCallDetailByCallId(request);Assert.equal(response.code, 'OK', 'queryCallDetailByCallId is failed!');
}

Darabonba 的主要能力是支持到不同风格的 OpenAPI,同时支持多语言的 SDK、Code Sample 目标生成。最终的目的仍然是打通从 OpenAPI 定义到文档、到 SDK、CLI 等 OpenAPI 使用场景下的一致性。提供给用户更统一、专业、一致的使用体验。同时也大幅降低 OpenAPI 提供者用来支持用户的成本,通过自动化的方式,节省精力的同时,还可减少人为参与时导致的错误。

参与贡献

Darabonba 的目标是让用户得到极致的 OpenAPI 体验,所以我们也需要更多的人参与到我们的开源项目来,大家可以按以前的方式参与 Darabonba 的贡献:

  • 参与其他语言生成器的生成,目前 Darabonba 只支持了比较常用的六门语言,还需要更多生成器的支持。
  • 编写更多底层工具模块,使 Darabonba 能够生成更便捷的 SDK。
  • 参与 Darabonba 编译器及 CLI 工具的建设中来。
  • 编写更多 OpenAPI 元数据转换到 Darabonba 的工具。

相关阅读

[1]Darabonba 上手文档
https://github.com/aliyun/darabonba#%E6%96%87%E6%A1%A3
[2]Darabonba CodeSample 示例
https://darabonba.api.aliyun.com/tutorial/demos
[3]Darabonba:支持任意 OpenAPI 网关的多语言 SDK 方案

原文链接:https://developer.aliyun.com/article/771250?

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

如何实现 OpenAPI 多语言 SDK 开发?相关推荐

  1. TeaDSL:支持任意 OpenAPI 网关的多语言 SDK 方案

    正在上传-重新上传取消 导读 在以云计算为主角的开发者视界中,OpenAPI 是绝对的主角.要发短信,用 OpenAPI:要管理资源,用 OpenAPI:要管理权限,用 OpenAPI.如果一个 Op ...

  2. [go学习笔记.第二章] 2.go语言的开发工具以及安装和配置SDK

    一.工具介绍: 1.Visual Studio Code 一个运行于Mac,Windows,和linux上的,默认提供Go语言的语法高亮的IED,可以安装Go语言插件,还可以支持智能提示,编译运行等功 ...

  3. mixin network_基于Mixin Network的Go语言比特币开发教程 : 用 Mixin Messenger 机器人接受和发送比特币...

    基于Mixin Network的Go语言比特币开发教程 : 用 Mixin Messenger 机器人接受和发送比特币 在 上一篇教程中, 我们创建了自动回复消息的机器人,当用户发送消息"H ...

  4. 游戏开发需要具备哪些技术_短视频 SDK 开发 (一) 开发一款短视频 SDK 需要具备哪些知识?...

    前言 2020 年要属什么最火,肯定是短视频和直播带货了.我自己基本上每天晚上睡觉之前都会刷一会儿 douyin 短视频,不得不承认 douyin 的推荐算法是真 nb ,推荐的都是我的最爱 ? .那 ...

  5. android sdk build-tools_从零开始仿写一个抖音App——视频编辑SDK开发(一)

    本文首发于微信公众号--世界上有意思的事,搬运转载请注明出处,否则将追究版权责任.交流qq群:859640274. 大家好久不见,又有一个多月没有发文章了.不知道还有哪些读者记得我的 从零开始仿写抖音 ...

  6. 提升普适性,阿里云官方SDK发布支持Go语言SDK

    摘要: 日前,阿里云官方SDK发布支持新语言--Go 语言SDK,意味着90%以上产品可以随时生成并发布Go SDK,给Go语言的开发者使用. 此次阿里云发布支持Go SDK的新功能,可以让Go语言开 ...

  7. cpprestsdk编译安装linux,使用C++ REST SDK开发简单的Web(HTTP)服务

    C++ REST SDK是微软开源的一套客户端-服务器通信库,提供了URI构造/解析,JSON编解码,HTTP客户端.HTTP服务端,WebSocket客户端,流式传输,oAuth验证等C++类,方便 ...

  8. 实际开发的存储过程_实际生产中的 Android SDK开发总结| 完结

    本文作者 作者:brucevanfdm 链接: https://zhuanlan.zhihu.com/p/163899902 本文由作者授权发布. 上一篇我们介绍了 SDK 开发的: 开篇与设计 Ex ...

  9. APP定制开发:APP软件开发的语言和开发环境

    APP软件开发是移动互联网开发公司常开发的一种手机应用系统,对于刚刚进入APP软件开发领域的新手来说,选择什么编程语言和需要什么开发环境来开发APP软件是常遇到的问题.下面亿合科技小编来为大家分享下: ...

最新文章

  1. 51nod 1073 约瑟夫环
  2. 最短路径·三:SPFA算法 HihoCoder - 1093 (spfa无向图)
  3. MySQL计算在线时长(超过2分钟未上传不在计算范围)
  4. Boost:bimap便利性标题的测试程序
  5. Unix基本操作指令备忘
  6. C++给函数传数组参数C++给函数传数组参数
  7. HDU3507 Print Article(斜率优化dp)
  8. 用pc浏览器打开手机页面
  9. 京东质检报告要求和检测项目-京东质检报告怎么弄
  10. 题目 1097: 蛇行矩阵
  11. 计算机游戏图形是什么意思,专业图形显卡和游戏显卡区别
  12. ubuntu进不了系统
  13. 日撸代码300行:第二天
  14. Google JavaScript规范
  15. 从三个方面说明0是无穷小
  16. OpenART mini使用教程
  17. 服务器压力测试工具0——需求与设计
  18. Java开发入门教程!java破解版游戏免费下载
  19. vue高德、谷歌地图动态加载
  20. 三星 联通 i9502 root 未安装su二进制

热门文章

  1. 牛逼!Python函数和文件操作(长文系列第3篇)
  2. 赶快卸载!微软新公布了18个流氓浏览器插件!
  3. 阿里云网盘开放申请!非会员下载 10MB/s!
  4. 最全的 pip 使用指南,50% 你可能没用过。
  5. js uri解码_js进行URL编码(escape,encodeURI,encodeURIComponent)
  6. memcached客户端_小水谈Memcache---Memcached安装
  7. 深度学习-Tensorflow2.2-深度学习基础和tf.keras{1}-线性回归tf.keras概述-02
  8. 动态规划,分治,回溯法,全排列,切片
  9. mybatis的插件分析
  10. [TCP/IP] 关闭连接后为什么客户端最后还要等待2MSL