3

学习 OpenAPI 的一点记录

 11 months ago
source link: https://www.raychase.net/7260
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

学习 OpenAPI 的一点记录

我记得在毕业以前,就大致明白这样一件事情,系统之间、模块之间的交互,要确定协议,要定义接口,兜兜转转这些年过去了,我觉得对这件事情认识当然越来越深刻,也说不清其中的程度。最近做的项目中,开始大量地和 OpenAPI 打交道,一方面要最先使用 OpenAPI 来定义接口,让多个其他交互的模块都遵循它来开发,就是 “OpenAPI Driven Development” 的意思,这没啥特别的;但另一方面,系统中还需要把 Protobuf 接口定义转换成 HTTP 接口定义,并实施地使用 swagger-core 来动态创建 OpenAPI Spec,这就比较好玩了。

artifacts-formats-1024x259.png

gRPC 到 HTTP 的协议转换

先来说说这第二件,动态创建 OpenAPI Spec。我们的网关系统需要大量地涉足两种接口,一种是对内调用 gRPC 接口,需要使用 Protobuf 来描述它们;另一种则是对外开放 HTTP 接口,需要使用 OpenAPI 来描述它们。这就牵涉到了两个事情:

  • 一个是需要设计一种机制,允许用户只用某一种描述语言(可以是 Protobuf,也可以是 OpenAPI)做出接口定义,然后这个定义会被自动转述为另一种接口定义语言,从而实现通过最少的配置,将两种接口都定义清楚了。技术实现上,我们使用了 Wire
  • 第二个是对于任何一个从外部到来的 HTTP 请求,这个系统需要根据定义自动把他转成 gRPC 的请求,并调用相应的内部系统,等到得到 gRPC 响应之后,也相应地转成 HTTP 响应并返回给外部。技术实现上,我们使用了 Vert.x

在这个过程中,我也学到了很多有意思的内容。一个是关于协议转换的,必须要完整地了解 Protobuf 是怎样描述一个接口的,而 OpenAPI 又是怎样描述一个接口的,然后才能谈转换,二者在定义上是有一些无法共同覆盖的部分的,这就需要使用某些替代或者扩展机制;再一个是基于 coroutine 或者 reactive 的异步编程(有的子系统基于前者,有的则是后者),以往写的 service 多数都是 blocking 的,适应 non-blocking 的 service 整个思维模式需要做一个转变。这部分体会还是比较深的,后续再写一点理解和总结。

OpenAPI Spec 驱动开发

再来说说这第一件,接口定义来驱动开发,这本来是一个平平无奇的事情,我记得 OpenAPI 的名字还是 Swagger 的时候就在项目中开始大范围地使用了,可是这一次,我才慢慢体会到它的威力远不止此。

使用 OpenAPI spec 来定义接口,不只是确定了所谓的系统和模块之间的合约(其实合约这一点其实使用任何方式来表述接口都可以做到);它还做到了一点,那就是 “标准化”。或者说,写这个合约的语言,叫做 OpenAPI,它是世界通用的语言,用它写出来的合约叫做 OpenAPI spec,大家都能看得懂。

Control Plane 中多模块对 OpenAPI Spec 的依赖

整个系统可以大致分为 Data Plane 和 Control Plane,前者可以说覆盖了从请求抵达、分解、协议转换,到内部接口调用,并将结果再次转换后返回的过程;而后者则是提供一系列机制和工具,去完成定义和控制这个过程所需的接口定义、序列化、持久化、请求校验、接口版本管理等一系列操作。

OpenAPI spec 是 Control Plane 整个系统中最重要的一个依赖项,有了它以后,很多模块都可以完成它相应的任务,无论是开发上,还是这些模块工作上,它们都可以并行。比如说,校验模块可以根据 OpenAPI spec 来校验外来的 HTTP request 和内部转换 gRPC 响应得到的 HTTP response 是否严格符合 spec 的格式;外部的客户端团队可以获取 OpenAPI spec 来自动生成客户端 SDK;接口定义人员可以在完成 protobuf 的定义后立即查看自动生成的 OpenAPI spec 是否符合他的预期等等。

OpenAPI 工具

有了 OpenAPI spec,或者说围绕它,就可以创造一系列的工具,并且这其中的许许多多都可以自动完成。OpenAPI.Tools 就是这样一个汇聚一系列 OpenAPI 工具的网站,而且基本上都是开源的,许多项目里面都可以比较自由地使用。我自己尝试了其中的一些,也实际用到了一些,我把其中比较有用的,记录在这里:

Avantation

可以根据 HAR 文件来生成 OpenAPI spec. HAR 就是 HTTP Archive format,是一种记录浏览器交互数据的 JSON 文件。上面有全部的访问某个网址的记录,包括 http 头、请求、响应和时间等等信息。

比如我们访问 https://reqres.in/api/users?page=2,然后就可以使用 Chrome 的开发者工具来导出 HAR 文件:

image.png
npm install -g avantation
avantation get_user.har
✔ GET /api/users/2
✔ all taskes completed

接着就可以查看生成的 openapi.yaml 这个 OpenAPI spec 了.

Swagger CLI

这个功能就可多了,比如可以校验 OpenAPI spec 的格式,合并 spec 等等。

npm install -g @apidevtools/swagger-cli

安装好后,跑一下格式校验:

swagger-cli -d validate ./spec.yaml
{
"command": "validate",
"file": "./spec.yaml",
"options": {
"schema": true,
"spec": true,
"format": 2,
"type": "json",
"wrap": null,
"debug": true
}
}
./spec.yaml is valid

Vacuum

这个就是 OpenAPI 的 linter:

brew install daveshanley/vacuum/vacuum

可以生成各种格式的结果页面,比如:

vacuum html-report ./spec.yaml
image.png

OpenAPI-diff

这个东西用来做 backward compatibility 的检查是个不错的选择。

安装就是一个 docker 镜像:

docker pull openapitools/openapi-diff

对比两个 OpenAPI spec 的版本:

docker run --rm -t \
-v ~/Downloads/open_api:/open_api \
openapitools/openapi-diff \
--fail-on-incompatible \
/open_api/spec.yaml \
/open_api/spec-updated.yaml
...
- GET /endpoints
Parameter:
- Delete input in query
API changes broke backward compatibility

Redoc

可以生成精美的接口文档。

npm i -g redoc-cli
redoc-cli build ./spec.yaml

OpenAPI Generator

可以根据 OpenAPI spec 生成客户端、服务端 stub、文档等等,非常好用。

brew install openapi-generator
openapi-generator generate -i spec.yaml -g kotlin -o output-client
openapi-generator generate -i spec.yaml -g kotlin-spring -o output-server

上面的例子中,第一个生成客户端,第二个生成服务端。其中参数-g 是可以用来指定某一种生成器

Swagger UI

Swagger UI 大概是这些工具里面我用的最早的,可以比较方便地查看 spec 并个根据它构造请求。

docker pull swaggerapi/swagger-ui
docker run -p 80:8080 -e
SWAGGER_JSON=/open_api/spec.yaml -v
~/Downloads/open_api:/open_api swaggerapi/swagger-ui

运行起来后就可以通过 http://localhost/访问了。

Restish

Restish 非常好用,我们部署的 service 需要使用命令行(CLI)来访问,以作为 portal 访问的一个功能上更强大的备选方案,可是去写 commandline 和维护挺费劲的,Restish 可以自动生成这样的命令行。

brew tap danielgtaylor/restish && brew install restish
restish api configure rest-example
restish rest-example get-endpoint --service abc --name def

上例中,第一行用来打开交互界面做初始化配置,以从远程 URL 读取指定 OpenAPI spec,第二行则是根据它来进行真正的 API call。

TCases

它可以用来自动生成远程 API 的测试代码,也是比较实用的。

./tcases-4.0.1/bin/tcases-api-test -o
./tcases-output/src/test/com/xyz/openapi -u 10000 -m
2 -l stdout -B uri=https://www.xyz.com/v1/abc ./spec.yaml

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《四火的唠叨》

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Comment *

Name

Email

Save my name, email, and website in this browser for the next time I comment.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK