From 2c8ba685a32f7a7726f366a5551208bfc580c065 Mon Sep 17 00:00:00 2001 From: CaptainNEO Date: Mon, 7 Mar 2022 21:23:06 +0800 Subject: [PATCH] add goa description Update README.md add placeholders add pl fix typo && add some useful external docs fix typo && add some useful external docs --- README.md | 239 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 203 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 065801e..643bf52 100644 --- a/README.md +++ b/README.md @@ -1,58 +1,223 @@ +[[_TOC_]] + # OpenAPI3 Framworks Compare 本文会横向对比几种支持OpenAPI文档生成的工具/框架。 -OpenAPI 规范(OAS)定义了一个标准的、语言无关的 RESTful API 接口规范,它可以同时允许开发人员和操作系统查看并理解某个服务的功能,而无需访问源代码,文档或网络流量检查(既方便人类学习和阅读,也方便机器阅读)。正确定义 OAS 后,开发者可以使用最少的实现逻辑来理解远程服务并与之交互。 +OpenAPI Specification(下文简称OAS)定义了一个标准的、语言无关的 RESTful API 接口规范,它可以同时允许开发人员和操作系统查看并理解某个服务的功能,而无需访问源代码,文档或网络流量检查(既方便人类学习和阅读,也方便机器阅读)。正确定义 OAS 后,开发者可以使用最少的实现逻辑来理解远程服务并与之交互。 此外,文档生成工具可以使用 OpenAPI 规范来生成 API 文档,代码生成工具可以生成各种编程语言下的服务端和客户端代码,测试代码和其他用例。OpenAPI官方提供了各种语言的服务端和客户端的代码生成工具,比较著名的如[OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator),当然也有很多优秀的第三方开发者开发的工具。 -> 相关参考 +> 参考阅读 > > - [OpenAPI3 Specification官方文档(v3.0.3)](https://spec.openapis.org/oas/v3.0.3) Published 20 February 2020 > - [OpenAPI3 Specification官方文档(v3.1.0)](https://spec.openapis.org/oas/v3.1.0) Published 15 February 2021 > - [Awesome OpenAPI3](https://apis.guru/awesome-openapi3) -## 1. 背景描述 +## 1. 项目背景 -使用如上几种框架分别实现Swagger官方用例[petstore](https://petstore.swagger.io)中的一部分,然后分析这些框架的实现方式,和背后生成OpenAPI的逻辑 +目前公司内部开发中的项目存在很多接口文档规范不统一、实现不一致的问题。据笔者的了解,起码目前存在以下的几种维护方式。 + + 1. 使用[swag](https://github.com/swaggo/swag)工具在代码中加入注解,然后通过代码生成对应项目的文档 + 2. 一些使用grpc-gateway的grpc项目会使用其附带的[protoc-gen-openapiv2](https://github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2)工具对protobuf文件进行分析,生成对应的文档 + 3. 在yapi中手撸接口文档 + 4. 纯手动,自己维护一个自定义格式的HTML文档 + +其中前两种方式使用工具生成,后两种完全靠双手自行维护。除第二种方式外,其他三种方式都多少依赖维护者的自觉性,维护得好皆大欢喜,维护得不好就会引发一系列的连锁反应。 + +- 新人接手项目。目前维护的这个服务提供了哪些能力?接手新需求的时候我是要新增一个接口还是已经存在类似的接口,只需要扩展一下?如果没有完整的接口文档,只能硬啃现有代码。如果代码量比较巨大的话会非常痛苦,或者疑惑我应该信代码还是信文档?会不会是代码实现有失误的地方?总之满头问号 +- 前后端对接、服务间对接。参数描述基本靠飞书,返回描述基本靠Chrome开发者工具。一个维护得足够久的接口没有人能够描述出来到底返回什么样的结构,需要传递哪些参数,怎么传,哪些必传,这些参数有哪些约束条件,或者一些已经废弃的参数可能早就无人使用,但是没人敢删除。到达某种状态后只能是懒得细扣代码,继续往上加。 总结:口头对接一时爽,事后复盘火葬场。 +- 重构。项目到达一定的复杂程度、或者随着产品的不断迭代,接口可能会面临着重构。如果没有足够的测试代码且对接口行为没有完全十足的把握的话,重构无疑会存在着巨大的风险,一不小心在某个获取参数的地方导致行为不一致、或者返回的结构有差别的话就会导致整个下游服务的行为异常。 + +这也是OAS存在的理由,如果所有的服务都使用了某种方式能从代码中生产出对应可信赖的、接口描述与代码行为严格同步的OAS文档,上述的所有问题都会迎刃而解,而且可以利用上社区内已经非常丰富的OAS生态相关工具,包括sdk生成、文档渲染工具等等。因为所有的文档都是标准的规范,甚至可以团队自己开发自己需要的工具,提升开发效率。一旦完善趋于完善,还可以做一些更有趣的事情,比如: + +1. 公司内所有服务,可版本溯源的HTTP API接口文档查询工具。 +2. 接通内管平台,对所有服务的接口管理。设定接口权限?联动网关层(如Istio)实现一个可视化的流量看板? + +既然如上列举的各种优势,现在摆在眼前的问题只有一个,那就是实现代码和OAS文档同步带来的额外工作量和难度,如果开发流程对开发者过于繁琐且耗时,那么必定在推广的时候困难重重。所以现在的情况就是寻找一个可以快速、简便地维护OAS文档的方法: + +1. 找现成的开源方案 +2. 自己造轮子 + +知己知彼,才能百战不殆。所以本项目的目的就是借鉴前人的设计和想法,总结好的设计方法,摒弃不好的设计方法。尽可能多的去了解别人是怎么做这件事情的,才能更好地去完成自己的。 + +以下内容会分别使用几种包含`从代码中同步文档`feature的框架(欢迎补充),用其实现一些简单的用例,然后分析这些框架的实现方式,和背后生成OAS的逻辑。随后会加上一些笔者的主观评价。 ## 2. 参赛选手介绍 -| 语言 | 框架 | Web功能完备 | OpenAPI版本 | Github Stars | 当前版本 | first release datae | -|--------|--------------------------------------------------------------------------|-------------|-------------|--------------------------------------------------------------------------------|------------------------------------------------------------------------------------|---------------------| -| Go | [goa](https://github.com/goadesign/goa) | 是 | 3 | ![stars](https://img.shields.io/github/stars/goadesign/goa.svg) | ![Release](https://img.shields.io/github/tag/goadesign/goa.svg) | 2016-08-03 | -| Go | [swag](https://github.com/swaggo/swag) | 否 | 2 | ![stars](https://img.shields.io/github/stars/swaggo/swag.svg) | ![Release](https://img.shields.io/github/release/swaggo/swag.svg) | 2017-11-30 | -| Go | [grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway) | 是 | 2 | ![stars](https://img.shields.io/github/stars/grpc-ecosystem/grpc-gateway.svg) | ![Release](https://img.shields.io/github/release/grpc-ecosystem/grpc-gateway.svg) | 2016-07-11 | -| Go | [fizz](https://github.com/wI2L/fizz) | 是 | 3 | ![stars](https://img.shields.io/github/stars/wI2L/fizz.svg) | ![Release](https://img.shields.io/github/release/wI2L/fizz.svg) | 2019-11-06 | -| Python | [Django REST framework](https://github.com/encode/django-rest-framework) | 是 | 3 | ![stars](https://img.shields.io/github/stars/encode/django-rest-framework.svg) | ![Release](https://img.shields.io/github/release/encode/django-rest-framework.svg) | 2011-02-22 | -| Python | [FastAPI](https://github.com/tiangolo/fastapi) | 是 | 3 | ![stars](https://img.shields.io/github/stars/tiangolo/fastapi.svg) | ![Release](https://img.shields.io/github/release/tiangolo/fastapi.svg) | 2018-12-16 | -| Rust | [Poem](https://github.com/poem-web/poem) | 是 | 3 | ![stars](https://img.shields.io/github/stars/poem-web/poem.svg) | ![Release](https://img.shields.io/github/tag/poem-web/poem.svg) | 2021-10-14 | +| 语言 | 框架 | Web功能完备 | OpenAPI版本 | Github Stars | 当前版本 | first release date | +|--------|--------------------------------------------------------------------------|-------------|-------------|--------------------------------------------------------------------------------|------------------------------------------------------------------------------------|--------------------| +| Go | [goa](https://github.com/goadesign/goa) | 是 | 3 | ![stars](https://img.shields.io/github/stars/goadesign/goa.svg) | ![Release](https://img.shields.io/github/tag/goadesign/goa.svg) | 2016-08-03 | +| Go | [swag](https://github.com/swaggo/swag) | 否 | 2 | ![stars](https://img.shields.io/github/stars/swaggo/swag.svg) | ![Release](https://img.shields.io/github/release/swaggo/swag.svg) | 2017-11-30 | +| Go | [grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway) | 是 | 2 | ![stars](https://img.shields.io/github/stars/grpc-ecosystem/grpc-gateway.svg) | ![Release](https://img.shields.io/github/release/grpc-ecosystem/grpc-gateway.svg) | 2016-07-11 | +| Go | [fizz](https://github.com/wI2L/fizz) | 是 | 3 | ![stars](https://img.shields.io/github/stars/wI2L/fizz.svg) | ![Release](https://img.shields.io/github/release/wI2L/fizz.svg) | 2019-11-06 | +| Python | [Django REST framework](https://github.com/encode/django-rest-framework) | 是 | 3 | ![stars](https://img.shields.io/github/stars/encode/django-rest-framework.svg) | ![Release](https://img.shields.io/github/release/encode/django-rest-framework.svg) | 2011-02-22 | +| Python | [FastAPI](https://github.com/tiangolo/fastapi) | 是 | 3 | ![stars](https://img.shields.io/github/stars/tiangolo/fastapi.svg) | ![Release](https://img.shields.io/github/release/tiangolo/fastapi.svg) | 2018-12-16 | +| Rust | [Poem](https://github.com/poem-web/poem) | 是 | 3 | ![stars](https://img.shields.io/github/stars/poem-web/poem.svg) | ![Release](https://img.shields.io/github/tag/poem-web/poem.svg) | 2021-10-14 | -## 3. 实现过程介绍 +## 3. 详细对比 + +所有框架均会从以下几个方面进行讨论 + +1. 开发过程 +2. OAS的实现方式: 如何从代码生成对应的sepc文件 +3. 优点:该框架的一些特色或者相比其他框架有优势的地方 +4. 缺点:该框架的一些劣势,或者不使用的理由 + +> 以下所有评价均为个人意见,欢迎不同意见 ### 1. Goa -```bash -## 1. 安装goa提供的代码生成工具 -go install goa.design/goa/v3/cmd/goa@v3 +#### 1. 开发过程 -## 2. 创建一个design文件夹,用于描述API -mkdir -p goa_example/design +1. 安装goa提供的代码生成工具 -## 3. 使用goa提供的dsl描述API + ```bash + go install goa.design/goa/v3/cmd/goa@v3 + ``` -## 4. 生成代码模板 -goa gen goa_example/design -# 该步骤会生成gen文件夹中的所有文件,包括design文件中定义的所有接口信息、Model描述、验证方式、Protobuf描述(如果有)等所有相关信息的Go描述 +2. 创建一个design文件夹,用于描述API -## 5. (optional) 生成实现的一个example -goa example goa_example/design -# 该步骤会生成cmd文件夹,包括http server和 grpc server的启动 -# 和项目根目录/{service_name}.go的文件,其中包含了各方法的默认实现(fmt.Println()) -# 接下来只需要修改各方法中的具体实现为真实业务逻辑即可 -``` + ```bash + mkdir -p goa_example/design + ``` -1. 优点 +3. 使用goa提供的dsl描述API +[desigin.go](go/goa_example/design/design.go) + +4. 生成代码模板 + + ```bash + goa gen goa_example/design + ``` + + 该步骤会生成gen文件夹中的所有文件,包括design文件中定义的所有接口信息、Model描述、验证方式、Protobuf描述(如果有)等所有相关信息的Go描述 + +5. (optional) 生成实现的一个example + + ```bash + goa example goa_example/design + ``` + + 该步骤会生成cmd文件夹,包括http server和 grpc server的启动代码 + 和项目根目录/{service_name}.go的文件,其中包含了各方法的默认实现(fmt.Println()) +6. 完成代码实现 + + 接下来只需要修改各方法中的具体实现为真实业务逻辑即可[service1.go](go/goa_example/service1.go) + +#### 2. OAS的实现方式 + +OAS中的所有对象均使用框架自定的DSL实现,定义design.go文件的同时,gen程序可以获得一个API的所有描述信息。 +然后根据这些描述信息,代码生成所需要的各种类型和interface、包括OAS描述文件,让用户尽可能的少写重复代码,只去完成关键逻辑。 + +#### 3. 优点 + +1. 可同时生成HTTP和Grpc两种服务,对应的实现比较完整,基本可以描述所有类型的API, +2. 生成的代码质量比较高,提供的代码抽象比较好。基本上只需要完成业务逻辑的实现就可以。其中甚至包含了分别使用http和grpc请求远端的命令行请求工具 + +#### 4. 缺点 + +1. 提供的DSL学习曲线很高,其基于查询调用栈的API设计,使得所有的函数均为灵活的不定长interface{}传参,除非熟练工,否则因为没有任何代码提示导致使用体验非常差。 +2. Model的描述方式虽然定制能力比较高,但是定义过程相当繁琐,不够直观。 +3. 使用时需要对OAS有足够的了解,否则不能很好地去合理设计API。 +4. 社区内相对比较小众。(6年积累了star 4.5k) +5. 因为定制程度非常高,可能导致一些特殊情况需要自定义http行为不容易实现。 + +### 2. swag + +#### 1. 开发过程 + +#### 2. OAS的实现方式 + +TODO + +#### 3. 优点 + +TODO + +#### 4. 缺点 + +TODO + +### 3. grpc-gateway + +#### 1. 开发过程 + +#### 2. OAS的实现方式 + +TODO + +#### 3. 优点 + +TODO + +#### 4. 缺点 + +TODO + +### 4. Fizz + +#### 1. 开发过程 + +#### 2. OAS的实现方式 + +TODO + +#### 3. 优点 + +TODO + +#### 4. 缺点 + +TODO + +### 5. Django REST Framework + +#### 1. 开发过程 + +#### 2. OAS的实现方式 + +TODO + +#### 3. 优点 + +TODO + +#### 4. 缺点 + +TODO + +### 6. FastAPI + +#### 1. 开发过程 + +#### 2. OAS的实现方式 + +TODO + +#### 3. 优点 + +TODO + +#### 4. 缺点 + +TODO + +### 7. Poem + +#### 1. 开发过程 + +#### 2. OAS的实现方式 + +TODO + +#### 3. 优点 + +TODO + +#### 4. 缺点 + +TODO ## 4. FAQ @@ -70,12 +235,14 @@ Swagger最初是在2010年设计RESTful API的简单开源规范。还开发了 此后,Swagger已成为最受欢迎的工具套件,可在整个 API 生命周期中充分利用 OAS 的强大功能。 SmartBear Software 支持的 Swagger 工具是最流行的实现 OpenAPI 规范的工具之一,并将继续保持 Swagger 名称(Swagger Editor、Swagger UI、SwaggerHub 等) +> 参考阅读 + ### 2. JSON Schema? - JSON Schema 是一种定义JSON格式的规范,相关生态已经比较完备,各种语言的校验工具基本都有实现。 - 例如vscode中配置文件的代码补全和校验就是基于json schema完成的。 +例如vscode中配置文件的代码补全和校验就是基于json schema完成的。 +JSON Schema 是一种定义JSON格式的规范,相关生态已经比较完备,各种语言的校验工具基本都有实现。 - OpenAPI中对Json对象的描述就是使用Json schema来描述的 - 目前为止已经发布了多个版本的草案,其中 - OAS3.0.3 采用的是Draft 00 - OAS3.1.0 采用的是Draft 2020-12 +OpenAPI中对Json对象的描述就是使用Json schema来描述的 +目前为止已经发布了多个版本的草案,其中 +OAS3.0.3 采用的是Draft 00 +OAS3.1.0 采用的是Draft 2020-12