IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    学习 OpenAPI 的一点记录

    四火发表于 2023-06-17 18:01:36
    love 0

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

    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 文件:

    安装:

    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
    

    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
    

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

    你可能也喜欢看:

    1. 关于 Jeff Dean 的几个搞笑传言
    2. XML 和 JSON
    3. 常见分布式应用系统设计图解(十):电商秒杀系统
    4. 常见分布式应用系统设计图解(一):即时消息系统
    5. 实际技术选型的考虑因素


沪ICP备19023445号-2号
友情链接