凌云时刻 · 技术

导读:朴灵是活跃在 Github 上的国内技术大牛之一。在阿里工作 6 年之际,朴灵产生了离职的想法,打算去一家创业公司再战高峰。走之前,朴灵做了一些研究工作,他发现阿里云在功能和产品上是一流的云计算厂商,可以说是创业公司的首选。但由于过去的业务中写过大量的 Node.js SDK,对开发者体验有着自己的体感,他觉得在开发者体验关怀上,阿里云做得还不够好。来自一个热血工程师最朴素的想法,自己何不先留下来,去把这件事情做好?于是,朴灵加入了阿里云开放平台负责 SDK 业务。期间,他和团队研发了专利 TeaDSL,下面朴灵将分享 TeaDSL 如何解决多语言 SDK 的问题。

作者 | 朴灵(田永强)

前言

在以云计算为主角的开发者视界中,OpenAPI 是绝对的主角。要发短信,用 OpenAPI;要管理资源,用 OpenAPI;要管理权限,用 OpenAPI。如果一个 OpenAPI 解决不了你的问题,那就再来一个。

在今天,开放平台及 OpenAPI 是一个到处可见的状态,它是系统与系统之间集成的重要桥梁。但 OpenAPI 用起来是否真的舒服,这要打一个大大的问号。本文将介绍 OpenAPI 领域下的难题和一些解决方案。

使用 OpenAPI 的痛苦

在过去,我们经常说的 OpenAPI,通常的做法是,开发好服务端的接口,然后在文档里简单写几个参数描述,就直接丢给客户去用。反正我是开发好了,我这里是好的,客户能不能用起来我是不用管的。

图 1 第一代的 OpenAPI

通常仅由简单的文档及实际的接口构成

然而接下来的问题就来了。首先,文档上写得不清不楚的参数,没有试过,完全不知道它到底能不能 Work。其次,OpenAPI 总得有一定的权限认证吧,那么总得有一个签名啥的,每个客户都要写一遍,关键是总是没法写对。再次,不同的客户所使用的编程语言不一样,得把接口重新包装才能用。

总算费心费力调通了接口,以为可以高枕无忧的时候,咋接口老是报错,网络连不上,返回的数据不对,诸如此类。再往后,OpenAPI 可能总是要发生一点变化什么的,总是出现一些数据结构发生变化,不兼容之类的问题。

一个 OpenAPI 到最后,不光是用户使用起来觉得很气,作为维护者也是很艰难的。当公布一个 OpenAPI 后,第一步给出简单的文档后,会发现除了要把参数详情写得越来越完善准确外,还得给出签名算法,让不同语言的开发者来接入。然而给出签名算法后,会发现只有一些开发者能顺利完成,大部分的开发者只能眼巴巴地请你帮忙提供一个 SDK。好吧,那就提供一下我最拿手的 Java 语言的签名,提供一个核心 SDK 呗。

图 2 第二代的 OpenAPI

会有 SDK 的实现,但仅有少许的语言支持

随着这个 OpenAPI 接口的用户越来越多,一个客户说我要用 C++ 来对接你,另一个客户说我要用 Python 来对接你,于是,我一个 Java 程序员,怎么就要写那么多语言的 SDK 呢。没有办法,如果不提供良好的 SDK,客户说,没有 IDE 提示呢,我怎么写代码呢。

总而言之,在 OpenAPI 的应用过程中,一件简单的事情,会变得非常复杂:

  • 需要提供良好的 API 文档,作为最基本的要求

  • 需要提供 SDK,保障开发者的编码体验,封装细节,代码提示等

  • 需要提供 Code Sample,更理解接口的使用效果

  • 如果有 CLI 就更好了,这样连 bash 脚本写起来也更方便

  • 如果没有 Test Cases 作为日常的持续集成,接口质量可能存在问题

上面这些要求,如果加上多种编程语言的条件,就会演变为一件细碎而又繁多的体力活。并且这中间不能有任何的变动,因为仅仅是一点点的 OpenAPI 变动,就需要连带整个下游发生变化。如果一个地方没有保持一致,那么客户问题就会出现。

图 3 当用户量变多,OpenAPI 的提供者需要提供完善的工具及更多的编程语言支持

通常为了解决此类的问题,以及 OpenAPI 的诸如签名校验,限流,生成 SDK、文档等等,业界通常会使用 API 网关来承担这些横向的责任。

然而,作为笔者所在的环境下,会发现,我们身边的网关有点多。于是不同的网关有不同的风格,不同的签名算法,不同的序列化格式。于是上述的过程要根据不同网关的数量,进行翻倍:

图 4 当一个企业变得庞大时

不同风格的 OpenAPI 及网关都会出现

当我们在抱怨使用不同产品的 OpenAPI/SDK 体验不一致,文档不对,Demo 出错等等问题时,真不是因为做这些事情太难,而是太多,太琐碎。一件简单的事情,需要做一百次,也就不是简单的事情了。

TeaDSL的解决之道

TeaDSL 是由阿里云开放平台 SDK 团队主导设计的一门领域特定语言。主要用于解决如下问题:

  • 通过一门中间语言,可以支持不同风格的网关。即使网关下的 OpenAPI 风格各异,也能一致地表达到。

  • 可以通过翻译的能力,实现对不同编程语言的代码生成。也就是可以基于统一的中间表达,生成多语言的 SDK。

  • 基于中间表达,我们可以将一组 OpenAPI 视为一个 library,因此可以在这个基础上实现 OpenAPI 接口的 Code Sample 编写。进而实现多语言的 Code Sample 统一生成。

因此 TeaDSL 的核心能力就是通过一种中间语法来描述 OpenAPI,提供类似编程语言的能力,来将 OpenAPI、SDK、Code Sample 等场景及语言有机地结合在一起。

在没有 TeaDSL 之前,对于不同的网关,我们要为它制定独立的工作流程,即从 OpenAPI 定义到不同语言的 SDK 生成,是独特的。换一个新的网关风格,就要重新实现这套流程。

图 5 M 个网关都要支持 N 种编程语言

整个工作量是 M * N 的关系

而具有 TeaDSL 后,我们则形成一个中间层。可以将原来的工作收敛起来,我们仅需要关注不同的网关到 TeaDSL 的转换工作,以及 TeaDSL 到各个编程语言的生成工作。

图 6 经过中间层的隔离

整个工作量变为 M + N 的关系

也就是说,TeaDSL 是在做一件 M * N 到 M + N 的工作。当网关越多,支持的编程语言越多,收益则越大。

一旦这个中间层建立起来,整个 OpenAPI 的应用形式都可以基于它来构建。比如,编写一个 OpenAPI 的 Code Sample,Test Case 等。

接下来简单介绍 TeaDSL 是如何实现支持任意风格的网关和多种编程语言的。

如何支持任意风格的网关

对于不同的 API 网关,或者不同产品的 OpenAPI 而言,它们之间的风格可能都千差万别,因此在很大的程度上,每种风格的 OpenAPI 都有它自己的元数据定义格式。为了减少网关、风格带来的差异化,业界主要推动的方式是尽量采用标准的定义格式。比如 Swagger 就是其中的佼佼者,它依托于 OpenAPI Specification ,以 RESTful 风格的 OpenAPI 作为基准,形成了一套业界标准。

但这个世界就是这样不完美,我们现有的大量 OpenAPI 并不是 RESTful 风格的。这导致很多的产品现存的 OpenAPI 在文档、SDK等场景下,无法使用上 Swagger 这样强大的生态工具链。

为了解决这些问题,我们需要进行两步操作:

  • 设立一套新的标准,来包容不同风格的 OpenAPI

  • 以这套新的标准,来建设生态工具链

如果完成这两个步骤,那么现实世界上的每一个 OpenAPI,RESTful 或者非 RESTful 的,不需要做任何迁移,也能具有强大的工具链支持。

新标准的设计

通过我们的研究发现,无论 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 风格差异,实质则是序列化过程不同而带来的不同。我们序列化过程和数据模型分离,将用户更直观的数据结构提取出来。

比如从用户角度出发,一个数据模型是更直观的事物:

model User {    username: string,  age: number}

在不同的网关下,它的传输形式可能是 JSON,也可能是 XML,但最终都是 readable,也就是可读的字节流。

toJSON(user: User): stringtoXML(user: User): string

最终的结果就是:

__request.body = toJSON(user);__request.body = toXML(user);

更进一步的过程是,我们会将一个 OpenAPI 的请求/响应包装为一个类似于编程代码的方法:

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

尽管上面的代码不能实际运行,但大致也看出来我们包容不同的网关、风格的办法如下:

  • 以 request / response 也就是 HTTP 协议作为核心模型

  • 通过引入一些方法,如 toJSON / toXML / readAsJSON 等方法来分离数据结构和序列化过程

  • 将整个过程包装成方法

这些方法在不同的编程语言下具有不同的实现,但我们只要定义好统一的签名,就能确保一致性:

function toXML(data: $Model): string;function toJSON(data: $Model): string;

以上就是 TeaDSL 如何实现支持任意网关的方案。整个过程相对抽象,网关间的那些具有差异化的风格,统统交给这些方法去实现,留下来的就只有数据结构。

如何支持不同的编程语言

如果只是能通过一种描述方式来描述不同的 OpenAPI 调用过程,只是完成了一半的工作。另一半的工作是如何将这种描述语言落地到不同的编程语言下。在过去,我们支持不同的编程语言,主要是基于模版的形式来生成不同语言的实际代码。但这对我们来说仍然还有一些不足之处:

  • 模版的生成方式相对生硬,实现起来容易,但维护起来不那么灵活

  • 生成出来的代码容易带来命名冲突,语法错误等

从上面的形式也看到,这个方案,被我们设计成了一种 DSL 代码。因此它是具有自己的词法、语法、语义规则的,在生成目标编程语言代码之前,会有一套自身的校验。DSL 的这些能力是模版所不具备的。

可能对于别的场合,采用 DSL 的形式并不多见。但对于前端工程师而言,这些年已经见的较多了:CoffeeScript、Babel、JSX、TypeScript 等等。为此我们参考了诸多编程语言的设计,最终形成了自己的一套语法。并借鉴编译器领域的转译方式,因此我们可以在模型一致的情况,生成到各种不同的编程语言下。

整个 TeaDSL 的处理流程如下:

最终我们支持多种编程语言的场景主要有3个:

  • 基本的多种语言的 SDK

  • OpenAPI 相关的多种语言的 Code Sample

  • OpenAPI 相关的多种语言的 Test Case

通过中间语言的强校验,生成到多种目标场景,可以解决编程语言支持不全面的问题。同时也大幅节约 OpenAPI 维护者的精力成本,不需要反复手工地编写不同编程语言下的 Code Sample。随着对不同编程语言的支持逐步完善,这些中间 TeaDSL 代码不需要任何操作,即可自动支持到新的编程语言下。

总结

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

目前 TeaDSL 在阿里云的一些 SDK 上已经有所应用,如:https://github.com/aliyun/aliyun-ccp。阿里云开放平台在持续努力提升它的整个工具支持生态,以期望能建成比 Swagger 更适配的生态体系。

END

往期精彩文章回顾

央行DECP开测,拉开全球货币霸权之战大幕

超算简史:练飞天之技,登峰一战后,终有落地日

面试了一个 46 岁的程序员,我思绪万千

重磅!阿里云操作系统团队连续发表 4 篇重量级论文

超越极限:阿里云最新ASPLOS论文解读

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

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

朴灵:云计算的开发者视界中,OpenAPI 是绝对主角 | 凌云时刻相关推荐

  1. 微软在2022年Gartner云计算AI开发者服务魔力象限中被评为“领导者”

    在2022 Gartner® Magic Quadrant™ 云计算AI开发者服务上,微软的服务获得了Gartner的认可,在"愿景完善度"坐标轴上处于最远端. 根据Gartner ...

  2. 朴灵:打破限制,从前端到全栈

    非商业转载请注明作译者.出处,并保留本文的原始链接:http://www.ituring.com.cn/article/197773 朴灵,真名田永强,文艺型码农,Node.js布道者.现就职于阿里巴 ...

  3. 在 Chrome 开发者工具中调试 node.js

    命令行工具 devtool ,它可以在 Chrome 的开发者工具中运行 Node.js 程序. 下面的记录显示了在一个 HTTP 服务器中设置断点的情况. 该工具基于 Electron 将 Node ...

  4. 又见灵异事件,li中的span右浮动遇到的问题

    最新又见灵异事件,li中的span右浮动遇到的问题 以下是三零网为大家整理的最新又见灵异事件,li中的span右浮动遇到的问题的文章,希望大家能够喜欢! 新闻列表中为了显示时间,加了个span < ...

  5. 请参阅:Chrome开发者工具中的悬停状态

    我希望看到:hover我在Chrome中徘徊的锚点的:hover样式. 在Firebug中,有一个样式下拉列表,允许我为元素选择不同的状态. 我似乎无法在Chrome中找到类似内容. 我错过了什么吗? ...

  6. Windows 8 HTML5/JS评论引发开发者群中的慌乱

    为什么80%的码农都做不了架构师?>>> Windows 8 HTML5/JS Comment Causes Panic Among Developers Windows 8 HTM ...

  7. 微软在Build 2016开发者大会中发布 “认知服务”,牛津计划有正式名字啦!

    2016年3月30日:微软在Build 2016开发者大会中发布"认知服务". 在Build 2016开发者大会中,微软发布了新的智能服务:微软认知服务(Microsoft Cog ...

  8. 如何让你在开发者工具中查看源代码有语法高亮和暗黑主题的效果

    如何让你在Chrome浏览器开发者工具中查看源代码的时候,和在代码编辑器中有同样的代码语法高亮的效果,而且还是深色主题,如果你是深色主题的爱好者就更合你意了. 国外的美女开发者为你实现了这样功能的浏览 ...

  9. 微信开发者工具中导入错误 提示请选择含app.json/project.config.json的目录(纪录篇)

    是因为每一次 npm run dev:mp-weixin 时都在编译dist/dev下的文件 所以在选择目录之前,要先找到自己创建的项目中的app.json文件,然后选择app.json文件的上级目录 ...

  10. v380怎么设置云存储_计算机网络云计算技术在应用中的不足及缺陷

    就目前计算机网络云计算技术的实际应用及发展情况而言,虽然得到一定的发展成果,然而这一技术在实际应用中仍有一定不足之处及局限性存在,在云计算技术的实际应用及发展中仍旧存在一定问题.在云计算技术的应用及云 ...

最新文章

  1. Class.forName( )你搞懂了吗?——转
  2. up 手环服务器不稳定,Up手环停产:曾经风光无限的Jawbone快不行了
  3. Android端打开HttpDns的正确姿势
  4. uln2003驱动蜂鸣器_让蜂鸣器发声
  5. 网络层核心:路由和路由生成算法
  6. LeetCode 662. 二叉树最大宽度(递归)
  7. 在公司拿了奖,发了点奖金
  8. java8 sum_Java8的Stream流真香,没体验过的永远不会知道!
  9. cut最后几位 shell_shell命令_cut
  10. B00001 C语言动态存储分配空间作为数组
  11. opencv 多边形近似物体形状
  12. FTP、TFTP、NFS、SSH介绍及在 Ubuntu 上的安装配置
  13. 01 Python基础
  14. FL studio20.9中文版水果编曲软件更新介绍
  15. 【盘点】电影中八大邪恶的超级计算机
  16. excel联系导入到手机通讯录(小米手机)
  17. html轮播鼠标悬停效果,jQuery图片轮播加悬停效果
  18. 初中学历可以学软件测试转行吗
  19. 远程连接windows 2012 是报出“出现身份验证错误,要求的函数不受支持”解决方法”
  20. 如何在-Mac-上强制退出应用

热门文章

  1. CopyTo 方法详解
  2. 委托的定义,与简单使用
  3. 论文阅读笔记——人脸网络:人脸识别和聚类的统一嵌入
  4. Python中系统命令
  5. 7-16 Sort with Swap(0, i)(25 分)
  6. [转载]用 FFMPEG 合并 MP4 视频
  7. iphone 开发设置tableview 初始位置。
  8. KR C C90,C99的改进
  9. 福建农林大学外事处界面设计
  10. 什么是传递(Pass-Through)会话