写点什么

干货丨基于 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:082341

评论

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

备忘录1

Vei

2021最新版阿里巴巴Java性能调优速成手册强烈推荐

比伯

Java 编程 架构 面试 架构师

区块链数字货币交易所系统软件APP开发

系统开发

android开发培训!深度解析跳槽从开始到结束完整流程,系列篇

欢喜学安卓

android 程序员 面试 移动开发

为什么你家的 K8s 应用平台不好用?

孙健波

Kubernetes PaaS KubeVela

架构师训练营第三周作业 -命题作业

阿德儿

认识产品经理(第一节)

让我思考一会儿

《价值》- 护城河(6)

石云升

读书笔记 护城河 28天写作

简单五步:利用Gitstats给代码仓库做一次体检

后台技术汇

28天写作

Hadoop编程实战:HDFS用户Shell详解

罗小龙

hadoop 最佳实践 28天写作 hdfs shell

Kafka 中的消息存储在磁盘上的目录布局是怎样的?

李尚智

Java kafka 架构 设计模式

Redis 学习笔记 08:数据结构与对象小结

架构精进之路

redis 七日更 28天写作

架构师训练营第三周作业 - 学习总结

阿德儿

volatile,还可以有这么硬的理解

Java 程序员 线程

万字带你深入阿里开源的Canal工作原理

大数据老哥

大数据 canal

新“庖丁解牛”,华为云技术全牛图解

陈泽涛

Android经典面试:46道面试题带你了解中高级Android面试,附面试题答案

欢喜学安卓

android 程序员 面试 移动开发

蝉联 Apache 最活跃项目,Flink 社区是如何保持高速发展的?

Apache Flink

flink

阿里云 RTC QoS 屏幕共享弱网优化之若干编码器相关优化

阿里云CloudImagine

音视频 WebRTC 网络 RTC 视频会议

一文读懂 Serverless,将配置化思想复用到平台系统中

Serverless Devs

Serverless 云原生 PaaS

AQS之ReentrantReadWriteLock精讲分析上篇

伯阳

AQS 读写锁 ReentrantReadWriteLock 多线程与高并发 lock

吉他谱怎么看?看谱大攻略送上!

懒得勤快

音乐 吉他学习 吉他谱 看谱

快了何止100%?阿里巴巴Java性能调优实战(2021华山版)PDF版开源

Java架构追梦

Java 阿里巴巴 架构 性能优化 华山版

EXCEL数据太“脏”无从下手?何须用python,ETL一分钟搞定

智分析

Excel ETL

图解分布式之:最终一致性,一致只会迟到,但绝不缺席

四猿外

架构 分布式 分布式系统 一致性 数据一致性

初步解析 Elasticsearch Document 核心元数据

escray

elastic 七日更 28天写作 死磕Elasticsearch 60天通过Elastic认证考试

Web UI自动化测试之元素定位

行者AI

软件测试 测试 自动化测试

【Redis】- Redis Cluser之数据分布

双木之林

第一周作业

Esther

【Java虚拟机】- Java虚拟机之逃逸分析

双木之林

阿里开源SpringSecurity:用户+案例+认证+框架

996小迁

Java 程序员 架构 面试 springsecurity

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