写点什么

干货丨基于 OAS 设计可扩展 OpenAPI

  • 2019-10-22
  • 本文字数:4317 字

    阅读完需:约 14 分钟

干货丨基于OAS设计可扩展OpenAPI

随着互联网行业的兴起,开发模式已逐步转换为微服务自治:小团队开发微服务,然后通过 Restful 接口相互调用。开发者们越来越渴望能够使用一种“官话”进行流畅的沟通,甚至实现多种编程语言系统的自动化交互。


开放 API 战略(Open API Initiativev)于 2017 年 1 月发表声明,2 月发布实现草案,经过反复讨论, 标准 API 规范 OAS(OpenAPI-Specification)3.0 版本在 2017 年 6 月诞生。


本文通过对 OAS 3.0 的分析解读,希望抛砖引玉,和大家一起了解 OAS 如何定义一种机器和人都能够发现与识别的规范,使得 OpenAPI 消费者可使用最小数量的实现逻辑来理解远程服务。

OpenAPI-Specification 规范架构

OAS 3.0 架构中将 OpenAPI 赋予了以下 8 个模块的定义,其中黄色模块为必选字段,绿色模块为可选字段:



各个主要模块工作流如下所示:



以下重点说明用户获取 OAS API 信息的三个必选部分:

01 API 基本信息

用户查询获取 OpenAPI 的基本定义及信息,涉及以下两个模块内容:


openapi


是否必选:必选


对象类型:String


类似于 XML 声明( ),用于设定文件应该使用哪一种规范进行解析。


info


是否必选:必选


对象类型:Info Object


这个模块主要提供 API 的元数据。


以下为一个 Info Object 样例:


title: Sample Pet Store App    #必须,应用名称description: This is a sample server for apetstore.   #应用的描述termsOfService: http://example.com/terms/      #应用的服务条款连接contact:      #应用提供商的联系方式   name: API Support   url: http://www.example.com/support   email: support@example.comlicense:   #应用所遵循的协议   name: Apache 2.0   url: http://www.apache.org/licenses/LICENSE-2.0.htmlversion: 1.0.1       #应用版本
复制代码

02 目标服务器信息

用户查询获取服务器的基本定义及信息,涉及以下模块信息:


servers


是否必选:必选


对象类型:[Server Object]


这个模块主要提供和目标服务器的连接信息,如果这个模块没有定义 url,根据规范会自动生成一个 url 为/的 Server Object。


例如:


servers:- url: https://development.gigantic-server.com/v1  #必选,  description: Development server   #非必选,url描述
复制代码

03 API 路径及定义

查询 API 具体参数,涉及 OAS 剩余的模块,本文主要介绍 paths 和 components 模块。


paths


是否必选:必选


对象类型:Paths Object


这个模块主要提供 OpenAPI 所在的目标服务器的连接信息,如果这个模块没有定义,根据规范会自动生成一个 url 为/的 Server Object。通过多级定义,分别确定 API 的 paths/method,并且通过 $ref 引用 comonents 模块中的定义,可以复用响应码等相关信息。对于携带 body 体的请求类型,requestBody 可以提供 example(或数组 examples),这是非常灵活的(可以传入一个完整的例子,一个参考,甚至是一个 URL 的例子)。


例如:


/pets:        #URL     get:     #方法,get/post/..             description: Returns all pets .    #描述                     responses:         #响应模块                         '200':         #返回码为200,可以使用通配符定义响应                                 description: A list of pets.    #响应描述                                 content:           #Content字段                                     application/json:                                                 schema:                                                             type: array                                                                      items:                                                                         $ref: '#/components/schemas/pet' #引用componets
复制代码


components


是否必选:非必选


对象类型:Components Object


这个模块主要提供每个 OpenAPI 自定义的字段定义,这部分定义的对象往往被 paths 中具体 API 进行引用:


−响应 responses


−参数 parameters


−示例 examples


−请求体 requestBodies


−标题 headers


−链接 links


−回调 callbacks


−模式 schemas


−安全体系 securitySchemes


以下为一个 Components Object 样例:


components:     schemas: #协议定义         Category:             type: object             properties:                 id:                         type: integer                         format: int64                 name:                         type: string         Tag:             type: object             properties:                     id:                         type: integer                         format: int64                     name:                         type: string     parameters: #参数定义         skipParam:             name: skip             in: query             description: number of items to skip             required: true             schema:                 type: integer                 format: int32         limitParam:             name: limit             in: query             description: max records to return             required: true             schema:                 type: integer                 format: int32     responses: #返回信息定义         NotFound:             description: Entity not found.         IllegalInput:             description: Illegal input for operation.     GeneralError:         description: General Error         content:             application/json:                     schema:                         $ref: '#/components/schemas/GeneralError'     securitySchemes:         api_key:             type: apiKey             name: api_key             in: header     petstore_auth:  #认证定义         type: oauth2         flows:             implicit:                     authorizationUrl: http://example.org/api/oauth/dialog                     scopes:                         write:pets: modify pets in your account                         read:pets: read your pets
复制代码

如何使用 OAS 设计可扩展的 OpenAPI

OpenAPI 规范包含一组有关如何设计 REST API 的强制性准则,首推协议优先的方法,而非实现优先,因此需要首先设计 API 接口,然后实现协定接口的代码。


如何实现一个优雅的 API 是一个非常具有挑战性的工作,开发者需要在庞大的后端系统的支持下,通过合适的方式将 API 暴露出去,除去单词拼写,路径设计等以外,设计优良的 OpenAPI 往往具有以下特性:

单一职责

单一职责是软件工程中一条著名的原则,实际在设计 API 时应确保每个 API 具有单一核心的职责,当某个 API 职责发生改变时不应该导致其他 API 发生故障和风险。OAS 中不同的 API 可以在 paths 模块中引用多个 schema,当我们设计新的 API 或者扩展原有 API 功能时,如果发现多个 API 多次引用相同 schema,需重点审视每个 API 是否仍然保持单一职责。

抽象 API

合适的抽象 API 与业务无关的,更通用,而且方便扩展。 具体的 API 接口设计能解决特定的问题,但是在系统的扩展性和普遍适用性上则相应欠缺,因此需要针对特定的场景分析,避免 over-designed(过度设计)和 under-engineering(懒惰设计)。


举个简单的例子,我们设计一个 paths 为/dog 的 API,那么这个 API 返回的是具体 dog 的相关信息,而如果我们进行抽象设计一个 paths 为/pet 的 API,将 dog 作为参数配置在 components 的 parameters 中,这样该 API 的扩展性进行了提升,后续扩展其他宠物比如 cat 的业务可以在不改变 API 路径的基础上进行开发,只需要更新 component 的 parameters 即可。

收敛 API

提供给用户的 OpenAPI 最好支持批量数据处理,而不是让用户一次一次地调用。通过考虑多个 API 间的关联性,让用户体会到 API 的简洁性。举例来说,如果用户有可能在调用 API2 之前需要 API1 的结果,那么 API 提供者应该把 API1 和 API2 进行包装。这会减轻用户的记忆负担,API 收敛需要符合最少知识的原则,作为用户应该对他所使用的系统有最少的了解,而不是过多介入到系统的细节中,因此在设计 API 时候,在满足用户诉求的情况下,components 模块字段越少越好。设计者往往容易在收敛 API 时候出现无法保证单一职责的原则的情况,好的设计需要在两者之间取得一个平衡,聚焦于最终的目的:让使用者快好省的用起来。

扩展机制

在设计 API 时需要考虑未来可扩展性,为后续 API 兼容历史 API 提供支持。一方面便于开发者自身增加功能,另一方面用户也能参与进来,共建 API 生态。通过设计定义 OAS,可以方便的按照 OAS 架构设计出面向对象、扩展性良好的 API。

版本控制

版本控制其实是扩展的一部分,鉴于大量项目在版本控制方面都做的比较糟糕,诸如随心所欲的版本命名、前后格式不一致的版本设定、没有规范的功能迭代,因此在大版本号不变的情况下,需要保障 API 向前兼容。当 API 的大版本号改动时,意味着 API 整体有大的改动,很可能不兼容之前的 API,同时可以提醒用户需要查询 API 更新文档进行适配,否则用户可能在更新 API 之后出现各种各样难以预测的故障。反之,如果修改小版本号则意味着这是个向前兼容的优化升级,用户可以在例行更新中采用新的 API。这种和用户约定好的默契,可以激发用户采用新版本的热情,而不是永远不升级依赖。

面向扩展开发

在通过 OAS 定义完相关信息之后,优雅的 OpenAPI 在开发过程中应着重思考 API 的可配置性,API 的实现应该面向修改开放的,因此需要将相关诸如参数校验、字段长度等配置项进行抽取,在提供默认配置项的前提下可配置可修改,同时应当允许配置项的新增,例如引入 java 的可变参数类型等,这样当 OAS 文档进行修改时,可以尽可能的较少整体 API 实现的变动量。


以上列举了优雅的 OpenAPI 所具有的部分特性,与其说 OAS 设计规范是一个强制的法则,不如说是一种引导式框架,开发者通过遵循规范从而实现高效的敏捷迭代。


当完成 OpenAPI 的设计开发之后,我们需要将 API 托管到合适的平台上进行能力开放,优秀的平台减少 API 提供者的工作量,抽取公共能力使 API 提供者更加专注于业务功能开发。华为云的 API 网关集成了监控、流控、负载均衡等一系列功能,可以为开发者提供高性能、高可用的 API 托管服务,实现个人、企业 API 能力的快速开放。


本文转载自公众号中间件小哥(ID:huawei_kevin)。


原文链接:


https://mp.weixin.qq.com/s/ZyswJu8pWxe1H0mdn_acVQ


2019-10-22 23:082095

评论

发布
暂无评论
发现更多内容

碳课堂|氢能--双碳目标下的未来能源之星

AMT企源

碳中和 新能源 碳管理 氢能

Svelte 最新中文文档翻译(3)—— 符文(Runes)上

冴羽

vue.js 前端 React Svelte SvelteKit

2025-01-22:使二进制数组全部等于 1 的最少操作次数Ⅱ。用go语言,给定一个二进制数组 nums,你可以对数组进行以下操作任意次(包括0次): 选择任何一个下标 i,并将从该下标开始到数组末

福大大架构师每日一题

福大大架构师每日一题

课程实录 | Ingress Controller 与 Master 的通讯机制

NGINX开源社区

Kubernetes k8s 学习资料 NGINX Ingress Controller kubernetes 运维

智慧菜场系统(源码+文档+部署+讲解)

深圳亥时科技

时序数据库 TDengine 与上海电气工业互联网平台完成兼容性认证

TDengine

tdengine 时序数据库

写代码的时候应该靠感觉还是靠理性

rubys_

AI赋能职场:提升效率还是加剧竞争?

天津汇柏科技有限公司

AI 人工智能

Bartender 5 for mac(菜单栏图标管理软件)v5.2.7中/英激活版

Rose

数字水印系统(源码+文档+部署+讲解)

深圳亥时科技

区块链智能合约的安全性

北京木奇移动技术有限公司

智能合约 区块链技术 软件外包公司

如何测量stp/step/prt等三维图纸?

在路上

cad cad看图 三维看图

Svelte 最新中文文档翻译(4)—— 符文(Runes)下

冴羽

Vue 前端 React Svelte SvelteKit

如何迅速并识别处理MDL锁阻塞问题

华为云开发者联盟

MySQL 华为云 GaussDB mdl TaurusDB

微帧科技携手行业精英,共编《移动场景扩展现实超高清技术白皮书》

微帧Visionular

EloqKV作为高性能缓存数据库的优势

晨章数据

数据库 分布式 dragonfly NoSQL 数据库

京东 API 接口调用失败的常见原因及解决方法

科普小能手

数据挖掘 数据分析 电商 京东 API 接口

牛牛剧场APP:小程序短剧投资引领创业新潮流

新消费日报

经典音频效果器合集:FabFilter Total Bundle 2019 mac破解版

Rose

AI口语练习的场景模拟

北京木奇移动技术有限公司

软件外包公司 AI口语练习 AI英语学习

新客户 | 时序数据库TDengine 携手新疆油田,让油气生产更高效

TDengine

tdengine 时序数据库

干货丨基于OAS设计可扩展OpenAPI_文化 & 方法_黄泽艺_InfoQ精选文章