凌云时刻 · 技术

导读:“阿里云的本质是一家卖 API 的公司。API 有没有做好,是关乎生死的大事。”

作者 | 普冬
来源 | 阿里云开放平台

前言

如今 OpenAPI 已经成为完成系统之间集成的重要桥梁,OpenAPI 的可用性以及客户在使用时的体验就变得越来越重要,阿里云前架构师曾说过:“阿里云的本质是一家卖 API 的公司。API 有没有做好,是关乎生死的大事。

但是从日常来自客户的反馈中我们总结了以下比较通用的几点OpenAPI体验问题:

  • 云产品 OpenAPI 没有提供 SDK 或者 SDK 语言不全;

  • 部分云产品的 SDK 使用风格差异过大,导致使用成本增加;

  • API 文档缺失或者不够清晰,不具备指导意义;

  • 没有场景化 CodeSample 或提供 CodeSample 无法运行

那么阿里云又该如何解决以上问题呢?本文就将通过客户调用阿里云 OpenAPI 服务所遇到的重点问题来介绍开源技术 Darabonba(原名 TeaDSL)是如何逐步解决的。

如何为任意风格的 OpenAPI 生成 SDK

说起生成多语言 SDK,大家第一时间想起的一定是当前业界内生成多语言 SDK 的通用方案——Swagger,开发者通过 Swagger 定义的 OpenAPI 标准并配合模板的方式来生成多语言 SDK。

不过问题并没有因此而得到完美的解决,首先模版的生成方式相对生硬,虽然实现起来容易,但维护起来却不那么灵活。其次,大量 OpenAPI 并不是 RESTful 风格的,这就导致很多的产品现存的 OpenAPI 在文档、SDK等场景下,无法使用上 Swagger 这样强大的生态工具链。例如,阿里云就有很多 OpenAPI 网关,不同的网关有不同的风格,不同的签名算法,不同的序列化格式,且都不是 RESTful 风格的 OpenAPI,所以导致了 SDK 风格差异大,也很难为所有的 OpenAPI 都提供 SDK 生成服务。

如果还沿用 Swagger 的模板生成的方式去生成如此之多网关的 SDK 生成器,先不说这些生成器后面是否还能维护,就算可以其工作量也是我们一个小团队所无法承担的。所以如何能够兼容所有网关生成风格统一的 SDK 就成了最主要的问题。

Darabonba 的解决之道

穷则变,变则通。

为了能够完成这个艰巨的挑战就不能沿用以前规范元数据的方法来解决,我们就需要对我们的工作重新进行抽象。在笔者看来,之所以没有一套元数据可以适用于所有的网关主要还是因为每个网关所对应的后端情况不同,就像机器语言或者汇编语言会因为架构的不同而有所不同,但是其本质还是描述如何通过操作寄存器、内存里的数据来完成一个程序。而对于 OpenAPI 来说也是同样的道理,所以我们通过重新定义一门 DSL 语言 Darabonba 来描述各种各样的 OpenAPI。

 基于 OpenAPI 的设计理念

通过我们的研究发现,无论 OpenAPI 的参数是如何组成的,传输是 JSON,还是 XML,乃至自定义协议,OpenAPI 都是基于 HTTP 协议栈进行提供的。也就是说,万变不离其宗的是 HTTP 协议本身。因此我们确立的基本模型是这样的:

{  protocol: string, // http or https  port: number,         // tcp port  host: string,         // domain  request: {    method: string, // http method    pathname: string, // path name    query: map[string]string, // query string    headers: map[string]string,  // request headers    body: readable      // request body  },    response: {    statusCode: number, // http method    statusMessage: string, // path name    headers: map[string]string,  // response headers    body: readable      // response body  },}

对于不同风格的 OpenAPI 而言,就像不同风格的建筑,它们的建筑材料都几乎相同,只是施工手法,组合形式不一样而已。我们看到的 OpenAPI 风格差异,实质则是序列化过程不同而带来的不同。我们序列化过程和数据模型分离,将用户更直观的数据结构提取出来,将数据结构都模型化,不管是 Request 的数据还是 Response 的数据,也不管它在 query,body 还是 header 里面都可以做成一个模型,例如:

// xx接口所用的User数据model User {  username: string(pattern='[a-zA-Z1-9]',description='username', name='username'),  age: number(pattern='\\d+',min='18',max='99',,description='age', name='age')}

这样的模型不仅能够帮助使用者以及维护者更好的了解该model的数据类型及介绍也能更好的了解到对数据的要求。而对于 OpenAPI 的请求/响应,我们则是通过 Darabonba 将其包装为一个类似于编程代码的方法:

import Util;api getUser(username: string): User {  __request.method = 'GET';  __request.pathname = `/users/${username}`;  __request.headers = {    host = 'hostname',  };} returns {  var body = Util.readAsJSON(__response.body);  return body;}

 AST 的妙用

通过 Darabonba 完成了对 OpenAPI 描述,其本质就是统一了元数据,只是这个元数据并不是 JSON 或者 Yaml 这样的方式来描述的,而是通过 DSL 代码来描述,Darabonba 的编译器则会将 Darabonba 的 DSL 代码转化为 AST,通过 AST 我们不仅可以生成多语言 SDK 也能生成 API 文档。整个 Darabonba 的处理流程如下:

同样的,我们也可以将各种网关的元数据转换为 Darabonba 的 DSL 代码,通过这样的方式再也不用为每个网关的元数据编写一套 SDK 生成模板了,而是只需要将元数据转换成 Darabonba 语言,复用 Darabonba 语言的各语言生成器能力即可生成多语言SDK,对于语言的扩展也方便了许多。也就是说,Darabonba 是在做一件 M*N 到 M+N 的工作。

目前通过 Darabonba 这门中间语言的帮助,我们团队在半年的时间中就为阿里云、蚂蚁链、支付宝、淘系等团队来自不同网关的上万个 OpenAPI 提供了 SDK 的生成支持。

通过将来自不同网关的元数据转换为统一风格的 DSL 所得到的 AST 数据不仅可以提供对于生成 SDK 的支持,而且也能优化相关 OpenAPI 的其他工具。例如阿里云的 OpenAPI Explorer 以往受限于 OpenAPI 风格问题,只能解析来自 POP 网关的 OpenAPI,所以能支持的 OpenAPI 仅限于 POP,但是在有了 Darabonba 以后就可以通过解析生成的 AST 来实现对于其他风格 OpenAPI 的接入以及生成相关 SDK 使用的逻辑代码。

 中心模块仓库

在 SDK 的编写中,仅仅通过 Darabonba 对 OpenAPI 的数据模型和请求/响应描述是不够的,还需要各种签名生成,文件上传,流操作等各种复杂的方法,所以为了能使生成的 SDK 更好用 Darabonba 中引入了模块化开发的理念。例如下面的代码中就引入了 Console 模块来打印字符串:

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

为了使生成的 SDK 更好用,目前提供了包含了常用方法的 Util 模块、文件上传所使用的 FileForm 以及 XML 模块等,同时开发者也可以自己编写相关工具类模块并发布到 Darabonba 模块仓库。

开发者在完成了 OpenAPI 的 Darabonba 代码编写以后,也可以通过 Darabonba 提供的 Darabonba CLI 将描述 OpenAPI 的 Darabonba 模块发布到模块仓库,这样使用 SDK 的用户就可以通过模块的详情页面查看 SDK 中包含的方法及各语言 SDK 的安装说明等信息了。

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

 CodeSample 自动生成

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

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

而通过引用模块仓库中 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 ID    config.accessKeyId = accessKeyId;    // 您的可用区ID    config.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);}

总结

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

 贡献指南

Darabonba 的目标是让用户得到极致的 OpenAPI 体验,这样的目标仅靠我们一个团队是很难完成的,所以我们也需要更多的人参与到我们的开源项目来,大家可以按以前方式参与进 Darabonba 贡献中来:

  • 参加阿里云组织的 CodeSample 全民赛码开发者挑战赛,不仅能通过 Darabonba 编写现有阿里云云产品 SDK 的 CodeSample 熟悉 Darabonba 并在使用过程中为 Darabonba 提出自己的建议还能赢取大疆无人机。

  • 参与其他语言生成器的生成,目前 Darabonba 只支持了比较常用的六门语言,还需要更多生成器的支持。

  • 编写更多底层工具模块,使 Darabonba 能够生成更便捷的 SDK。

  • 参与 Darabonba 编译器及 CLI 工具的建设中来。

  • 编写更多 OpenAPI 元数据转换到 Darabonba 的工具。

点击下方“阅读原文”了解更多 CodeSample 全民赛码开发者挑战赛

END

往期精彩文章回顾

阿里云吴天议:应用驱动云网络深度融合

如何轻松搞定SAP HANA数据库备份?

进阶之路:Java 日志框架全画传(下)

进阶之路:Java 日志框架全画传(中)

进阶之路:Java 日志框架全画传(上)

一款云迁移产品的成长史

情感分析技术:让智能客服更懂人类情感

电子书免费下载!1天上手的蓝牙Mesh应用解决方案来袭

语雀的技术架构演进之路

下一代异步 IO 技术解密

长按扫描二维码关注凌云时刻

每日收获前沿技术与科技洞见

Darabonba:多语言SDK开发终极解决方案相关推荐

  1. 如何实现 OpenAPI 多语言 SDK 开发?

    简介:由于每个网关所对应的后端情况不同,因此没有一套元数据可以适用于所有的网关.阿里云通过重新定义一门 DSL 语言 -- Darabonba 来支持不同风格的 OpenAPI,同时支持多语言的 SD ...

  2. UI开发的终极解决方案

    2019独角兽企业重金招聘Python工程师标准>>> 呵呵,有点标题党的意思,但是如果你正在寻找UI解决方案,你一定不会白来的. 虽然没有直接开发前台界面,但是好呆也看了这么些年, ...

  3. sublime配置python开发环境以及遇到的坑(附终极解决方案)

    最近一直在写python项目,在此之前我用的工具主要是pycharm,由于我的笔记本配置渣,每次打开pycharm后我都要去倒杯水,然后回来看看有没有打开我的项目,时间充足的时候还好,如果有同事或者领 ...

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

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

  5. Kinect for Windows SDK开发入门

    Kinect for Windows SDK开发入门(一):开发环境配置 首先来看一下Kinect设备: 1. Kinect设备 黑色的Kinect设备如下图:基座和感应器之间有一个电动的马达,通过程 ...

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

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

  7. mysql c 中文字符串_MySQL字符集中文乱码终极解决方案和mysql查询中文问题解决方法...

    开源数据库MySQL从来都是中小企业构建web应用的首选,特别是和PHP配合简直就是一 对黄金搭档,深受web开发人员的喜爱.但自从4.1以来MySQL加入了多字符集的支持,很多MySQL使用者发现中 ...

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

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

  9. php源码 乱码 通达oa_php中文乱码问题的终极解决方案汇总

    前言 本文主要给大家介绍了关于php中文乱码问题的终极解决方案,分享出来供大家参考学习,在开始之前,我们先来谈谈为什么会出现中文乱码? 很多新手朋友学习PHP的时候,发现程序中的中文在输出的时候会出现 ...

  10. 大疆Payload SDK开发火热来袭!

    DJI SDK开发课程之--大疆Payload SDK(PSDK)开发今日正式上线~ 本课程由「铂贝学院(阿木实验室)」联合DJI 大疆共同推出! 大疆PSDK开发课程介绍 DJI 为支持开发者开发出 ...

最新文章

  1. Focal Loss和它背后的男人RetinaNet
  2. shell编程系列15--文本处理三剑客之awk格式化输出printf
  3. dart参数传方法_为 JavaScript 开发人员准备的 Dart 参考教程
  4. 洛谷 P3994 高速公路
  5. SQL syntax-log2
  6. 汇编语言(二十四)之输出n行星号
  7. Java属性loadFromXML()方法与示例
  8. C++ 普通函数与函数模板 区别以及调用规则01
  9. 2007年淘宝网手机销量统计报告
  10. 【转】二维异形件排版算法介绍(二)
  11. LeetCode 1465. 切割后面积最大的蛋糕
  12. android 魅族短信拦截,如何防护手机里的个人信息?魅族18系列教你如何防范隐私泄露...
  13. lg函数c语言表达式,lgammal - [ C语言中文开发手册 ] - 在线原生手册 - php中文网
  14. 第六课-Android四大组件之Activity
  15. 用outlook登录163邮箱的超详细教程
  16. ad怎么修改栅格_AD软件的3种栅格设置详解
  17. 【等保小知识】等保、分保以及关保分别是什么意思?
  18. 自学python积累
  19. 【LeetCode】三维型体的投影面积和表面积
  20. usb禁止重定向_谈USB重定向的方式

热门文章

  1. MSR系列路由器DAR功能的配置
  2. ubuntu12.04-- vi 使用
  3. Zend Optimizer not installed可能原因及解决方法
  4. 第7章 XSL高级应用
  5. bay——RAC_ASM ORA-15001 diskgroup DATA does not exist or is not mounted.docx
  6. ThinkPHP中使用聚合查询去重求和
  7. Java基础增强:集合的嵌套案例
  8. 简述23种软件设计模式
  9. centos 安装qrcode  二维码
  10. ps 缩放 颜色分类 像素和分辨率学习笔记