一文带你详细了解Open API设计规范

news2024/11/18 7:23:19

写在前面:

OpenAPI 规范(OAS)定义了一个标准的、语言无关的 RESTful API 接口规范,它可以同时允许开发人员和操作系统查看并理解某个服务的功能,而无需访问源代码,文档或网络流量检查(既方便人类学习和阅读,也方便机器阅读)。正确定义 OAS 后,开发者可以使用最少的实现逻辑来理解远程服务并与之交互。

此外,文档生成工具可以使用 OpenAPI 规范来生成 API 文档,代码生成工具可以生成各种编程语言下的服务端和客户端代码,测试代码和其他用例。

在这里插入图片描述

背景

Open API 和前端页面一样,一直都是产品的门面, Open API 不规范,会拉低产品的专业性。在云场景下,很多用户会选择自建门户,对接云产品的 Open API,这对我们提出的诉求便是构建一套成熟的 Open API 机制。

站在业务角度,有一些指导原则,指导我们完善 Open API 机制:

  • 前端页面使用的接口和 Open API 提供的接口是同一套接口
  • 任意的前端页面接口都应该有对应的 Open API

最近由于业务需求,我参与研发的云产品 CSB 需要对外开放 Open API,原本不是什么难事,因为阿里云内部的 Open API 开放机制已经非常成熟了,根本不需要我去设计,但这次的需求主要是针对一些独立部署的场景,需要自行设计一套规范,那就意味着,需要对 Open API 进行一些规范约束了,站在技术角度,阿里云有很多的 API 开放标准可供我们参考,一些开源产品的 Open API 文档也都非常完善。

总之,一方面,我会取其精华,另一方面,要考虑自身产品输出形态的特殊性。本文将围绕诸多因素,尝试探讨出一份合适的 Open API 开放规范。

Open API 设计考虑因素

一个完善的 Open API 规范到底应该规范哪些东西?

站在设计角度,需要考虑:命名规范,构成规范,路径规范,出入参规范,数据类型规范,统一返回值规范,错误码规范,分页规范。

站在团队角度,团队中的后端初级中级开发以及前端研发是否有足够的经验,领悟并落地好制定的 API 规范。同时,伴随着人员流动,这份 Open API 规范是否可以很好地被传承下去。

站在行业角度,需要考虑提供 Open API 的产品所在的市场是否已经成熟,API 风格可能已经有了对应的规范。

站在产品角度,每个产品适合的 API 风格是不同的,下文会着重探讨这一角度。

总之,Open API 的设计是很难形成定论的一个东西,我在介绍自身产品最终采用的 Open API 规范之前,会先来聊一下大家耳熟能详的一些概念,例如 restful。

restful 规范之争

有人的地方就会有江湖。

有代码的地方也是如此。

如果你在码圈混,一定听说过 restful 规范:

  • 增删改查应分别声明为:POST、DELETE、PUT、PATCH、GET

  • 不应该出现动词,动词统一由 HTTP Method 表示

  • 体现出“资源”的抽象

  • 利用 pathVariable,queryParam,header,statusCode 表达很多业务语义

restful 规范看似美好,但如果你真正尝试过落地,一定会遇到一些类似的问题:

  • 以用户登录接口为例,此类接口难以映射到资源的增删改查
  • 以查询最近 7 个小时内的接口请求错误率为例,衍生到诸如 graphQL 这类复杂的查询场景,往往需要 json 结构,GET 是无法实现这一点的,只有 POST 才可以传递

基于此,restful 规范逐渐有了反对的声音:

  • 强行让所有的事物都“资源”化一下,有悖于开发常识,接口不一定都能够通过简单的增删改查来映射
  • 复杂的查询语义不一定能够用 GET 表达

restful 风格的拥趸者,不乏对这些反对言论进行抨击,社区中不免有“拒绝 restful 风格的主要是低水平不思进取的架构师和前后端程序员们,不会设计是人的问题,不是规范的问题”此类的言论。同时对 restful 进行了升华:复杂参数的检索问题,在 restful 语义中本就应当归类为 post,因为该行为并不是对资源的定位(GET),而是对资源的检索(POST)

这显然刺激了 restful 风格反对者的神经,不屑道:呵,愚蠢的 restful 原教旨主义者呀。

不知道你是 restful 的拥趸者还是反对者?亦或是,中立者。

restful 之争暂时到此为止,这番争论纯属虚构,看官不必计较。无论你如何看待 restful,下面我的论述,你都可以作为一个中立者,否则效果减半。

ROA 与 RPC

API 设计并不只有 restful 一种规范,在更大的视角中,主流的 API 设计风格其实可以分为

  • 面向资源的设计,即 ROA(Resource oriented architecture)
  • 面向过程的设计,即 RPC(Remote Procedure Call)

restful 便是 ROA 风格的典型例子,而 RPC 风格则相对而言不太容易被大家熟知,但实际上可能大多数的系统的接口是 RPC 风格的,只不过 RPC 风格这个概念不太为人所知。

以用户模块的 CRUD 为例,对比下两个风格:

ROA 风格

创建用户(POST)

Request:
POST /users

{"name": "kirito", "age": 18}

Response:
HTTP 201 Created

{"id": 1, "name": "kirito", "age": 18}

查询用户(GET)

Request:
GET /users/1

Response:
HTTP 200 OK

{"id": 1, "name": "kirito", "age": 18}

查询用户列表(GET)

Request:
GET /users

Response:
HTTP 200 OK

{[{"id": 1, "name": "kirito", "age": 18}], "next": "/users?offset=1"}

创建/修改用户(PUT)

Request:
PUT /users/1

{"name": "kirito", "age": 19}

Response:
HTTP 200 OK

{"id": 1, "name": "kirito", "age": 19}

修改用户(PATCH)

Request:
PATCH /users/1

{"age": 20}

Response:
HTTP 200 OK

{"id": 1, "name": "kirito", "age": 20}

删除用户(DELETE)

Request:
DELETE /users/1

Response:
HTTP 204 No Content

ROA 风格和 restful 规范说明的是一回事,为方便其与 RPC 风格接口的对比,特此说明上面示例的一些值得关注的点:

  • 使用 HTTP 响应码(200,201,204),完成 HTTP 语义与业务语义的映射,异常流也出现 404,401 等情况(出于篇幅考虑,本文未做异常流的介绍)
  • PATCH 部分修改资源,请求体是修改部分的内容;PUT 创建/修改资源,请求体是新资源全部的内容
  • id 是资源定位符,而 age、name 则为属性

RPC 风格

创建用户(POST)

Request:
POST /user/createUser

{"name": "kirito", "age": 18}

Response:
HTTP 200 OK

{"code": 0, "message": "", "data": {"id": 1, "name": "kirito", "age": 18}}

查询用户(POST)

Request:
POST /user/getUser

{"id": 1}

Response:
HTTP 200 OK

{"code": 0, "message": "", "data": {"id": 1, "name": "kirito", "age": 18}}

查询用户列表(POST)

Request:
POST /user/listUsers

Response:
HTTP 200 OK

{"code": 0, "message": "", "data": {"user": [{"id": 1, "name": "kirito", "age": 18}], "next": "/user/listUsers?offset=1"}}

修改用户(POST)

Request:
POST /user/modifyUser

{"id": 1, "name": "kirito", "age": 19}

Response:
HTTP 200 OK

{"code": 0, "message": "", "data": {"id": 1, "name": "kirito", "age": 19}}

修改用户名称(POST)

Request:
POST /user/modifyUserAge

{"id": 1, "age": 20}

Response:
HTTP 200 OK

{"code": 0, "message": "", "data": {"id": 1, "name": "kirito", "age": 20}}

删除用户(DELETE)

Request:
POST /user/deleteUser

{"id": 1}

Response:
{"code": 0, "message": ""}

RPC 风格不像 restful 一类的 ROA 风格存在一些约定俗成的规范,每个业务系统在落地时,都存在差异,故此处只是笔者个人的经验之谈,但愿读者能够求同存异:

  • user 为模块名,不需要像 ROA 风格使用复数形式
  • 使用明确的动宾结构,而不是将 CRUD 映射到 HTTP Method,HTTP Method 统一使用 POST,查询场景也可以使用 GET
  • 返回值中携带 code、message 和 data,来映射响应状态及响应信息,一般可以自行定义 code 的状态码,本文使用 0 标识请求成功,message 仅在业务响应失败时有意义,data 代表业务响应结果

如何选择 RPC 和 ROA,则需要根据产品自身的业务情况进行决策。有如下的指导原则:

  • 有复杂业务逻辑的 API ,无法使用简单的增、删、改、查描述时宜使用 RPC 风格。
  • 如果业务所属行业标准要求 restful 风格 API 或 ROA 能够满足业务需求,宜使用 ROA 风格。

AWS 主要采用 RPC 风格,Azure、Google 主要采用 ROA(restful)风格,阿里云 OpenAPI 同时支持 RPC 和 ROA,以 RPC 为主。

尽管规范是无罪的,但在 ROA 风格在实践过程中,我还是见识过不少“坑”的:

  • 要求资源先行,即先设计资源,后设计接口,对软件开发流程要求较高
  • 错误的 ROA 设计案例 1:tomcat 等应用服务器在处理 DELETE 方法的 HTTP 请求时,默认不允许携带 request body,需要显式开启,导致删除失败。(此案例为设计者的问题,复杂的删除场景,不应当映射成 DELELE,而应改成 POST,DELETE 不应当携带 request body)
  • 错误的 ROA 设计案例 2:restful 路径中携带的参数,可能会引发正则匹配的问题,例如误将邮箱作为路径参数,或者多级路径匹配的冲突问题(此案例为设计者的问题,复杂的查询场景,不应当映射成 GET,而应改成 POST,path 中只应该出现资源定位符,而不应当携带属性)
  • 响应码为 404 时,较难区分是真的 path 不存在,还是资源不存在
  • 不利于对接网关等需要配置路由转发的场景

CSB 的 Open API 规范希望满足以下的需求:

  • 后端开发设计接口时,有明确的设计思路,不至于因为一个接口到底用 POST 还是 GET 实现而纠结,不用花费太多时间在资源的抽象上(这并不是说明资源是不需要被设计的)
  • 前端开发对接接口时,能够较快地与后端协同,并且利于前端接口的封装
  • 用户对接 Open API 时,整体风格一致,模块清晰

综上,在设计风格选择上,我计划采取 RPC 的设计规范。总结一下 RPC 风格的优势:

  • API 设计难度较低,容易落地
  • 阿里云大多数成熟的 IAAS 层产品使用 RPC 规范
  • 适合复杂业务场景

一个详细的 RPC 接口文档示例

创建服务

请求参数

序号字段中文名字段英文名数据类型必填说明
1名称namestring显示名称
2协议protocolstring枚举值:http/grpc/webservice
3负载均衡lbstring枚举值:random/roundrobin
4上游类型upstreamTypestring枚举值:fixed/discovery
5节点列表nodesarrayupstreamType=fixed 时必填,示例:[{“host”: “1.1.1.1”,“port”: “80”,“weight”: “1”}]
6来源idoriginIdstring
7服务名称serviceNamestring注册中心中的名称,upstreamType=discovery 时必填
8服务描述descriptionstring
9网关idgatewayIdstring

返回参数

序号字段中文名字段英文名数据类型说明
1响应码codeint0
2响应信息messagestring
3响应结果datastring返回服务 id

请求示例

POST /service/createService

Request:
{
  "name": "httpbin",
  "protocol": "http",
  "lb": "random",
  "upstreamType": "fixed",
  "nodes": [
    {
      "host": "httpbin.org",
      "port": "80",
      "weight": "1"
    }
  ],
  "gatewayId": "gw-1qw2e3e4"
}

Response:
{
  "code": 0,
  "message": "",
  "serviceId": "s-1qw2e3e4"
}

API 命名规范

  • API 应使用拼写正确的英文,符合语法规范,包括单复数、时态和语言习惯

  • 不能出现多个含义相近但功能无实际差别的 API,如同时存在 /user/getUser 和 /user/describeUser

  • 语言习惯:禁止使用拼音

  • 如下常见场景的命名规则是固定的

    • 日期时间类型的参数应命名为 XxxxTime。例如:CreateTime
  • 常用操作名称规范

    • create:创建
    • modify:变更
    • delete:删除
    • get:获取单个资源详情
    • list:获取资源列表
    • establishRelation:建立资源关系
    • destroyRelation:销毁资源关系

总结

当我们讨论这种规范时,我们必须不断思考其目的和背景。在真实的生产环境中,我们不得不面对大量的代码量和不断增长的需求,因此,我们需要寻找一种能够提高协作效率和代码可靠性的方式,以确保能够更好地满足客户的需求。

使用 POST 接口是一种通用和标准的接口方式,这种方式能够最大程度上降低用户和开发人员之间的沟通成本,减少对接口额外理解的必要,同时也能够避免“GET”接口可能会造成的安全问题。

此外,这种规范化的接口方式还能够实现更佳的可维护性,因为在系统中所有的接口都遵循同一种标准,开发人员就能够很轻松地理解和修改这些接口,从而更快地定位和解决问题。

综上所述,使用 POST 接口是一个令人放心且具有潜在收益的做法。对于开发人员来说,这种规范化的方式会让他们更容易遵循接口设计规范并减少不必要的工作量,更好地完成工作任务。对于系统和公司来说,这种做法也能够提高系统效率、降低维护和错误定位成本,从而使整个团队更高效和有竞争力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/826717.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Atlas200DK A2联网实战

文章目录 1.Atlas原始网络信息2. 开发板联网2.1 使用Type-c 连接开发板2.2 修改本地网络适配器2.3 修改开发板网络信息2.4 测试外网连接 1.Atlas原始网络信息 Type-C 网口 ETH0 网口 ETH1 网口 2. 开发板联网 2.1 使用Type-c 连接开发板 使用xshell 等ssh终端登录开发板&…

【C++从0到王者】第十五站:list源码分析及手把手教你写一个list

文章目录 一、list源码分析1.分析构造函数2.分析尾插等 二、手把手教你写一个list1.结点声明2.list类的成员变量3.list类的默认构造函数4.list类的尾插5.结点的默认构造函数6.list类的迭代器7.设计const迭代器8.list的insert、erase等接口9.size10.list的clear11.list的析构函数…

【java安全】CommonsBeanUtils1

文章目录 【java安全】CommonsBeanUtils1前言Apache Commons BeanutilsBeanComparator如何调用BeanComparator#compare()方法?构造POC完整POC 调用链 【java安全】CommonsBeanUtils1 前言 在之前我们学习了java.util.PriorityQueue,它是java中的一个优…

2.2 身份鉴别与访问控制

数据参考:CISP官方 目录 身份鉴别基础基于实体所知的鉴别基于实体所有的鉴别基于实体特征的鉴别访问控制基础访问控制模型 一、身份鉴别基础 1、身份鉴别的概念 标识 实体身份的一种计算机表达每个实体与计算机内部的一个身份表达绑定信息系统在执行操作时&a…

3、详解桶排序及排序内容总结

堆 满二叉树可以用一个数组中从0开始的连续一段来记录 i i i位置左孩子: 2 ∗ i + 1 2*i+1 2∗i+1,右孩子: 2 ∗ i + 2 2*i+2 2∗i+2,父: ( i − 1 ) / 2 (i-1)/2 (i−1)/2 大根堆 每一棵子树的根为最大值 小根堆 每一棵子树的根为最小值 建大根堆 不断地根据公…

配置HDFS单机版,打造数据存储的强大解决方案

目录 简介:步骤:安装java下载安装hadoop配置hadoop-env.sh配置 core-site.xml配置hdfs-site.xml初始化hdfs文件系统启动hdfs服务验证hdfs 结论: 简介: Hadoop分布式文件系统(HDFS)是Hadoop生态系统中的一个…

【硬件设计】模拟电子基础二--放大电路

模拟电子基础二--放大电路 一、基本放大电路1.1 初始电路1.2 静态工作点1.3 分压偏置电路 二、负反馈放大电路三、直流稳压电路 前言:本章为知识的简单复习,适合于硬件设计学习前的知识回顾,不适合运用于考试。 一、基本放大电路 1.1 初始电…

数学建模-爬虫入门

Python快速入门 简单易懂Python入门 爬虫流程 获取网页内容:HTTP请求解析网页内容:Requst库、HTML结果、Beautiful Soup库储存和分析数据 什么是HTTP请求和响应 如何用Python Requests发送请求 下载pip macos系统下载:pip3 install req…

VactorCast自动化单元测试

VectorCAST软件自动化测试方案 VectorCAST软件自动化测试方案 博客园 软件测试面临的问题 有一句格言是这样说的,“如果没有事先做好准备,就意味着做好了 失败的准备。”如果把这个隐喻应用在软件测试方面,就可以这样说“没有测试到&#xf…

Tomcat虚拟主机

Tomcat虚拟主机 部署 [rootlocalhost webapps]# cd ../conf [rootlocalhost conf]# pwd /usr/local/tomcat/conf [rootlocalhost conf]# vim server.xml #增加虚拟主机配置&#xff0c;添加以下&#xff1a; <Host name"www.a.com" appBase"webapps"u…

react-redux的理解与使用

一、react-redux作用 和redux和flux功能一样都是管理各个组件的状态&#xff0c;是redux的升级版。 二、为什么要用reac-redux&#xff1f; 那么我们既然有了redux&#xff0c;为什么还要用react-redux呢&#xff1f;原因如下&#xff1a; 1&#xff0c;解决了每个组件用数…

怎么才能远程控制笔记本电脑?

为什么选择AnyViewer远程控制软件&#xff1f; 为什么AnyViewer是远程控制笔记本电脑软件的首选&#xff1f;以下是选择AnyViewer成为笔记本电脑远程控制软件的主要因素。 跨平台能力 AnyViewer作为一款跨平台远程控制软件&#xff0c;不仅可以用于从一台Windows电…

数据库监控平台,数据库监控的指标有哪些--PIGOSS BSM

引言 在现代企业的信息化时代&#xff0c;数据库作为关键的数据存储和管理工具&#xff0c;扮演着至关重要的角色。然而&#xff0c;数据库的稳定性和高效性对于企业的正常运营至关重要。为了帮助企业保障数据库的运行状态&#xff0c;我们公司推出了PIGOSS BSM&#xff0c;一款…

MySql006——基本的SELECT查询语句

在《MySql003——结构化查询语言SQL基础知识》中&#xff0c;我们学习了有关SQL的基础知识&#xff0c;也知道SQL中查询语句SELECT使用最为频繁 接下来我们将学习一些基本的SELECT查询语句 一、SELECT语句的通用语法 在MySQL数据库中&#xff0c;使用SELECT语句可以查询数据…

024 - mix()函数

定义&#xff1a;MIN()函数返回一组值中的最小值。NULL 值不包括在计算中。 语法&#xff1a; MIN(expression) 参数值&#xff1a; 参数 描述 expression 必须项。数值&#xff08;可以是字段或公式&#xff09; -- 实际操作&#xff08;查询最小工资数&#xff09;: SE…

绿盟认证概述

目录 1.前言 2.绿盟认证概述 1.前言 2020,沪漂上海,初入网安,干着安服,月薪8k,金牌代理,分享给大家。记得还拿下了绿盟的NCSA售后和售前的考证呢! 2.绿盟认证概述

【爬虫实践】使用Python从网站抓取数据

一、说明 本周我不得不为客户抓取一个网站。我意识到我做得如此自然和迅速&#xff0c;分享它会很有用&#xff0c;这样你也可以掌握这门艺术。【免责声明&#xff1a;本文展示了我的抓取做法&#xff0c;如果您有更多相关做法请在评论中分享】 二、计划策略 2.1 策划 确定您…

【ERROR】解决autodl 服务器Xshell7中Screen页面乱码

解决autodl 服务器Xshell7中Screen页面乱码 screen界面为乱码 查看Xshell7终端编码 查看服务器端编码 locale将其更改为UTF-8 export LANGzh_CN.UTF-8

银河麒麟V10 飞腾 Qt环境搭建

采用在线安装方式&#xff1a; 1、在线安装qt组件 sudo apt-get install qt5-* 2、在线安装qt creator sudo apt-get install qtcreator 以上简单两步安装完成后&#xff0c;新建项目已经可以编译过&#xff0c;但ClangCodeModel会报错如下图 the code model could not parse …

AdvancedInstaller打包程序

文章目录 1. AdvancedInstaller 下载2. AdvancedInstaller 启动3. 新建工程4. 配置安装包详细信息5. 配置安装参数6. 添加要打包的文件7. 设置安装完成后启动程序8. 构建打包 1. AdvancedInstaller 下载 下载网址&#xff1a;https://www.advancedinstaller.com/ 2. AdvancedIn…