RESTful API 设计规范

RESTful API 设计规范

A Good API

  • Provides A Good Mental Model

    考虑API的设计者、维护者、使用者在API生命周期内的互动:设计者应提供清晰的、易于理解的实体模型;维护者和使用者应对API有清晰的、一致的认识,以便对API的理解、调试、测试、扩展、维护。
  • Simple

    应避免在API中引入过多实现细节,或过度简化(避免出现简单调用也和复杂业务逻辑耦合的情况,以防暴露过多业务逻辑)。
  • Allows Multiple Implementations

    如果一个 API 自身可以有多个完全不同的实现,一般来说这个 API 已经有了足够好的抽象,也不会和外部系统耦合过紧。不同实现面向不同请求,在工程中可以采用不同的服务实例解决,通过访问不同endpoint配置来区分。

Well Documented

提供详细的API 文档可以提升团队整体的研发效率。API 的设计者和维护者应准确记录每个字段和方法,并保持文档更新。

内容包括但不限于:

  • 资源说明
  • 字段和参数说明:边界值,默认值,字符串允许的字符范围及编码方式,示例值,字段说明(必须/仅限输入/仅限输出)。
  • 方法说明:指明方法的效果及操作的资源。
  • 使用惯例

Resource Model

资源(Resource)是对一套 API 操作核心对象的抽象,设计 API 的一个重要前提是对资源本身合理定义。这种合理抽象应去除细节,具体实现留给具体系统处理。API 需要选择“对的”而不仅仅是简单的实体进行建模。

另外,不同层级的抽象方式可能在描述同一资源,但在概念上是面向不同层面的选择的。服务中数据对象的多层处理要求使用针对不同层的数据模型;便于明确服务本身的职责,也使API易于演进和维护。

Naming and Identification

API 的用词描述是云服务展现给外部用户的第一印象。
HTTP 协议中,最广为认知的是对 HTTP Mehod 的约定,使用9个单词(GET, HEAD, POST, PUT, DELETE, CONNECT, OPTION, TRACE)就完成了对基本动作的规范,为开发者提供了清晰的思维模型。同样,在 HTTP Header 里面也对浏览器信息、语言、网络连接属性等做了详细规定。这样开发者在使用 HTTP 服务时有一个大致约定,在关键信息上无偏差,保障了异构系统的接口一致性。因此,云服务在管理API 时应该考虑一些具体的规范,对命名规则、标准词汇、最佳实践模式、错误码等信息都有明确的规定,便于用系统化、平台化的手段管理API。

一般有两种暴露给用户的命名(Naming)/标识(Identification)方式,实际操作时按需选择。

注:如果已有字符串或结构化的标识,则不一定需要数字ID(慎用数字ID)。

注:API中暴露给用户的公共部分,应体现其用途,而非实现。

  • 采用free-form string
    • 优点:具体实现时自由度较大。
    • 缺点:命名的内在结构不属于API定义的一部分,而是属于实现细节;泄露实现细节可能导致安全性问题。
  • 采用结构化数据
    • 优点:如果资源对象的抽象模型本身包含结构化的标识信息,采用结构化的方式会简化客户端与资源的交互逻辑。这部分的业务逻辑是被描述系统的内在逻辑,而非实现细节;因此有助于简化具体实现,并且可以避免非结构化字符串带来的安全性问题。
    • 缺点:不同系统的具体实现可能导致已定义的结构不适用,标识也不具有灵活性。

Operations

实际业务中,操作并不总是CRUD(CREATE, READ, UPDATE, DELETE)的;针对具体的对象/资源需要定义语义和行为概念上合理的相应操作。

允许API 设计者自定义操作来实现无法映射到标准方法的功能。如果API 功能能够自然映射到标准方法,则应在API 设计中使用该方法。

  • 注:自定义并不意味着创建自定义HTTP 动词来支持自定义方法;对基于 HTTP 的 API 而言,映射到HTTP 动词最合适。

Idempotency

具备幂等性的操作可以多次进行且不会影响到第一次的结果。

  • CREATE 类型的幂等性

    多次调用容易产生重复创建,解决方案是在客户端生成唯一ID。
    在反复重试创建时使用这个ID,便于服务端识别重复创建操作。
  • UPDATE 类型的幂等性

    更新值存在两种语义:更新增量,和设置新的总量。后者更易具备幂等性;而前者在多个客户请求同时增加时更易于并行处理,此时应考虑使用唯一token解决更新值的幂等性。
  • DELETE 类型的幂等性

    重复删除已被删除的对象可能会因为数据无法找到而报错。严格意义上不幂等,但操作无副作用。

Compatibility

API的变更应支持向后兼容,确保客户端的使用不会被服务端的新版本中断。

实际中还应考虑如何做不兼容的API 变更。例如,删除一个方法/字段/枚举变量数值,方法/字段改名,方法/字段不做改变但其语义和行为发生变化(客户通常依赖API 语义和行为,即使此类行为没有得到明确记录)。

注:不兼容的变更需要通过 Deprecation Process,在大版本发布时分步骤实现。

注:任何向后兼容的保证只适用于公共接口。因此区分公共接口和内部接口很重要。

变更参考

  • 向后兼容的(非重大)变更
    • 向 API 服务添加 API 接口
    • 向 API 接口添加方法
    • 向方法添加 HTTP 绑定
    • 向请求消息添加字段
    • 向响应消息添加字段
    • 向枚举添加值
    • 添加仅限输出的资源字段
  • 向后不兼容的(重大)变更
    • 移除或重命名服务、接口、字段、方法或枚举值
    • 更改 HTTP 绑定
    • 更改字段的类型
    • 更改 proto 字段编号
    • 更改资源名称格式
    • 更改现有请求的可见行为
    • 更改 HTTP 定义中的网址格式
    • 向资源消息添加读取/写入字段

API Design

以 API 为中心完善相关体系,保障用户体验的一致性、及时性、稳定性、易用性。

API 是后端服务的外部表达。对于云服务商来说,应考虑选择支持哪种 API 风格才能更好地体现业务特性,让客户操作更方便。在选定具体模式后,要努力做到统一。

开发API 时应区分不同场景,做好元数据(Metadata)的管理。针对 API 是否开放要有明确的规范和度量机制,确保该开放的API 都可以开放、内外客户看到的功能集合基本一致,才能有利于云服务的更好集成。

以鉴权为例。权限在云平台中心一般是中心式管理;如果统一处理鉴权,就需要知道当前 API 正在操作什么资源,以及与此相关的资源都有哪些,然后针对相关资源逐一鉴权才能确认 API 操作是否可行。上述资源有两个关键点:一是要有统一的资源模型,便于云产品对特定的 API 鉴权;二是要明确资源关系,当出现资源依赖的时候,需要关联鉴权。

  • RPC(Remote Procedure Call):本地调用远程,是面向过程(Procedures, 也称为Functions;实体被隐藏在过程中)的调用。
    • API 组织形态为领域行为(对象和方法)。
    • 即便是RPC 风格的API,也要大致符合HTTP 规则,否则可能会给一些依赖HTTP Code的系统造成误导。
    • 方便客户端和服务器的本地编程;效率高,易于调用(类似库的调用)。但在软件后续需要技术/功能的改变及集成新服务的情况下灵活性较差。
    • 命名多为动词;URL没有约定规范,需要详细文档说明。
    • 支持的HTTP方法基本只用GET和POST。
    • RPC风格的API是偏向内部的API。
    • 适用目标:在用户管理的分布式部分之间需要交互,并且重点考虑处理效率时,建议使用RPC风格。
  • REST(Representational State Transfer):面向资源的调用。
    • API组织形态为资源实体,以资源为中心(设计时需要明确API提供的资源,资源间的关系和导航,资源URL结构,资源的结构体;一个URL代表一种资源)。
    • REST风格的API一般靠响应码来告知用户有什么问题;HTTP协议本身对错误码做出了详尽的规定,REST API要尽可能符合标准。
    • API需要有一致的接口来解耦(Decoupling)客户端和服务实现,便于后续集成新功能。
    • 命名API时暴露给用户的公共部分,应体现资源,而非动作。
    • 支持的HTTP方法包括GET, POST, PUT, DELETE。
    • REST风格的API是偏向外部的API。
    • 适用目标:在需要通过分解成为多个组成部分(相互之间独立更佳)来提高软件的延展性时,或需要开放系统以考虑未来集成其他团队的项目时,建议使用REST风格。这样任何从标准文档了解过HTTP的人都可以使用你的API,并且无需阅读过多API 实体模型文档和请求语法说明。

Error-handling

错误返回机制是用户使用API时的重要组成部分。最佳实践建议使用标准、统一的错误码(Error Code),如 HTTP 的规范错误码,而不是由每个API自建一套 Error Code 和返回错误机制。
客户端最关心的是当前error是否该重试,还是应该继续向上层返回错误。如果只传递错误信息,使用 Error message 里的字段即可,无需自定义更多错误码。

REFERENCE

[1] 阿里云 - API设计最佳实践的思考:https://yq.aliyun.com/articles/701810?spm=a2c4e.11153940.0.0.391b7163Hh6IrB
[2] Google Cloud - API Design patterns: https://cloud.google.com/apis/design/design_patterns
[3] Microsoft - API design best practices: https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design
[4] HTTP status code: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值