RESTful API 为何成为顶流 API 架构风格?
作者孙毅,API7.ai 技术工程师,Apache APISIX Committer
万物互联的世界充满着各式各样的 API ,如何统筹规范 API 至关重要。RESTful API 是目前世界上最流行的 API 架构风格之一,它可以帮助你实现客户端与服务端关注点分离,让前后端各自迭代,提升管理效率;其无状态的特性可以让应用更容易扩展,更容易的实现缓存策略从而提升系统性能和用户体验。本文将介绍什么是 RESTful API 以及我们如何使用它。
首先,抛开 API 这个概念,我们来聊聊在生活中如何传递信息。
当你在商店将钱拿给老板告诉他你需要买电池,老板在收到钱后在货架上找到电池并递给你。一个买电池的交易顺利完成。
计算机软件则通过 API 来完成信息的传递,先来看维基百科定义:
An application programming interface (API) is a way for two or more computer programs to communicate with each other. It is a type of software interface, offering a service to other pieces of software.
软件 A 通过 API 向软件 B 发起请求,软件 B 在查询自己资源后将请求的响应内容通过 API 返回 A。
软件 A 通过 API 向软件 B 发起请求就好比你跟老板说你需要电池,软件 B 在将数据返回给软件 A 就好比老板找到电池后将电池给你。
这一过程软件 B 不需要知道软件 A 为什么要数据,就好比商店老板不会问你买电池的目的。软件 A 也不需要知道 B 软件的数据是怎么找到的,就好比你买电池的时候你也不会问老板电池从哪里进货一样。每个软件之间通过 API 传递信息,各司其事,使得程序世界变得有序可靠。
什么是 RESTful API
Roy Fielding 在他 2000 年的博士论文《建筑风格和基于网络的软件架构设计》中定义了REST(Representational state transfer),REST 架构风格定义了六个指导性约束。一个符合部分或全部约束的系统被松散地称为 RESTful。
(图片来源:Seobility)
REST 的约束条件(长龙在排版时可以考虑一键截图 or 分点>横向叙述)
约束条件 | 详述 | 优势 |
---|---|---|
Client–server architecture | 通过将用户界面问题与数据存储问题分开,提高了跨多个平台的用户界面的可移植性,并通过简化服务器组件提高了可扩展性。 | 1. 客户端、服务端解耦。 2. 提升用户平台跨平台的可移植性。 3. 提升服务器端的可拓展性。 |
Statelessness | 客户端的每个请求到服务器必须包含请求所需的所有信息,并且不能利用服务器上存储的任何上下文,会话状态完全保存在客户端。 | 1. 易扩展,无会话依赖,任何服务器可以处理任何请求。 2. 易缓存,提升程序性能。 |
Cacheability | 要求请求响应中的数据被隐式或显式标记为可缓存或不可缓存。如果一个响应是可缓存的,那么客户端缓存就被授予为以后的等效请求重用该响应数据的权利。 | 1. 减少带宽。 2. 减少延迟。 3. 减少服务器负载。 4. 隐藏网络状态。 |
Layered system | 通过约束组件行为允许架构由分层层组成,这样每个组件都不能“看到”超出它们与之交互的直接层。通过将系统知识限制在单个层,降低了整个系统的复杂性并促进了底层独立性。 | 1. 降低整个系统的复杂性。 2. 促进底层的独立性。 3. 可方便的实施负载均衡。 4. 可将业务逻辑和安全策略解耦。 |
Code on demand (optional) | 允许通过下载和执行小程序或脚本形式的代码来扩展客户端功能。 | 1. 提高系统的可扩展性。 |
Uniform interface | 主要包含四点: 1. Resource identification in requests. 客户能够通过请求中包含的 URI 来识别一个资源,将服务端资源和客户端请求资源解耦。 2. Resource manipulation through representations. 当客户端拥有一个资源的表示,如 URI,那么就有足够的信息来修改或者删除资源。 3. Self-descriptive messages. 每个消息都包括足够的信息来告知客户客户端该如何处理该信息。 4. Hypermedia as the engine of application state (HATEOAS). 客户端不需要任何额外的编码通过服务端返回的资源链接,就可以使得用户获取所有的资源。 | 1. 简化了整体系统架构。 2. 提高了交互的可见性。 |
RESTful API 最佳实践
强调组件间的 统一接口 是 REST 架构风格与其他基于网络的风格区分开来的核心特征,基于此特征,本文梳理了RSETful 最佳实践,以帮助你更好的设计 API。
路径名称避免动词
使用 HTTP 方法来表达资源操作行为,而不是将行为动词定义到路径中。
// Good
curl -X GET http://httpbin.org/orders// Bad
curl -X GET "http://httpbin.org/getOrders"
- GET 获取指定 URI 的资源信息
// 代表获取当前系统的所有订单信息
curl -X GET http://httpbin.org/orders// 代表获取订单编号为 1 的订单详情信息
curl -X GET http://httpbin.org/orders/1
- POST 通过指定的 URI 创建资源
// 代表创建一个名称为 order 的资源
curl -X POST http://httpbin.org/orders \-d '{"name": "awesome", region: "A"}' \
- PUT 创建或全量替换指定 URI 上的资源
// 代表将 id 为 1 的 order 进行数据替换
curl -X PUT http://httpbin.org/orders/1 \-d '{"name": "new awesome", region: "B"}' \
- PATCH 执行一个资源的部分更新
// 代表将 id 为 1 的 order 中的 region 字段进行更改,其他数据保持不变
curl -X PATCH http://httpbin.org/orders/1 \-d '{region: "B"}' \
- DELETE 通过指定的 URI 移除资源
// 代表将 id 为 1 的 order 删除
curl -X DELETE http://httpbin.org/orders/1
URI 使用复数形式
若使用单数的形式来表示获取某一类资源,例如:
curl -X GET "http://httpbin.org/order"
使用单数形式,会使用户产生该系统中只有一个 order 的困惑,用复数形式在逻辑上则顺畅很多。
curl -X GET "http://httpbin.org/orders"
善用 HTTP 状态码
HTTP 标准定义个状态码,大致可以分为以下几类:
状态码 | 含义 |
---|---|
2xx | 成功,操作被成功接收并处理 |
3xx | 重定向,需要进一步的操作以完成请求 |
4xx | 客户端错误,请求包含语法错误或无法完成请求 |
5xx | 服务器错误,服务器在处理请求的过程中发生了错误 |
使用标准状态码,开发人员可以立即识别问题,可以减少发现不同类型错误的时间。
版本管理
随着业务需求的变更,已经上线的 API 大概率是要对应调整的。如果我们的 API 有第三方在使用,让每一个客户端根据我们 API 的变更而变更显然是不可能的,这个时候就要引入 API 版本管理概念了,既可以保证历史 API 正常使用,又可以迭代新的 API 以满足新的业务需求。
常见的版本控制手段有:
- 通过请求中路径来做版本控制
// 请求 v1 版本的API
curl http://httpbin.org/v1/orders// 请求 v2 版本的API
curl http://httpbin.org/v2/orders
- 通过 Query 参数来做版本控制
// 请求 v1 版本的API
curl http://httpbin.org/orders?version=v1// 请求 v2 版本的API
curl http://httpbin.org/v2/orders?version=v2
- 通过 Header 来做版本控制
// 请求 v1 版本的API
curl http://httpbin.org/orders -H "custom-version: v1"// 请求 v2 版本的API
curl http://httpbin.org/orders -H "custom-version: v2"
APISIX 如何助力 RESTful API
作为一个动态、实时、高性能的 API 网关,Apache APISIX 可以在任何 RESTful API 服务上运行,并使用插件来添加新的服务和扩展其功能,这符合 RESTful 定义中的 Layered system。此外,对于一些没有遵循 RESTful API 定义的历史服务, APISIX 也可以帮你在不改动原有业务代码的情况下完成接口的转换,使你的接口完成 Uniform interface 这一 REST 限制条件,使你的 API 可以更好的遵守 RESTful API 规范。
分层系统:支持业务逻辑和安全逻辑的分割
你可以只用关注业务逻辑的实现,接口的安全逻辑可以交给 APISIX Authentication 类插件处理,例如 key-auth。APISIX 支持大量的 Authentication 插件,我们以 openid-connet为例如下图所示:
我们可以看到,使用 APISIX(API Gateway)在业务服务器前面加一层认证逻辑,就可以起到保护上游服务的作用,让你的业务逻辑和安全逻辑高效解耦。
Layered system:多负载均衡协议支持
APISIX 作为 API 网关,可以设立在客户端和服务端之间,完成不同的负载需求。你甚至可以自定义负载均衡的逻辑。
支持的负载均衡算法有:
roundrobin
: Round robin balancing with weights.chash
: Consistent hash.ewma
: Pick the node with minimum latency. See EWMA Chart for more details.least_conn
: Picks the node with the lowest value of(active_conn + 1) / weight
. Here, an active connection is a connection being used by the request and is similar to the concept in Nginx.- user-defined load balancer loaded via
require("apisix.balancer.your_balancer")
统一接口:使历史 API 更加 RESTful
对于已经存在很久的历史 API,如果没有很好的遵循 RESTful API 准则。你可以在不改造原有 API 逻辑的情况下重新通过 APISIX 来封装新的 API 以满足不同的业务场景。
使用 proxy-rewrite 改写客户端请求
在本文中上方提过我们的路径中不要有动词。
例如:历史版本 API 有 /getOrder
接口,我们可以通过 proxy-rewrite
插件来将 API 请求代理到历史 API 上:
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{"methods": ["GET"],"uri": "/orders","plugins": {"proxy-rewrite": {"uri": "/getOrder","scheme": "http",}},"upstream": {"type": "roundrobin","nodes": {"127.0.0.1:80": 1}}
}'
你也可以同样使用该插件进行 API 版本管理上的操作。
使用 response-rewrite 插件改写服务端响应
当我们的历史 API 存在响应状态码不规范时,我们可以通过 response-rewrite 代理 response 响应从而达到修改响应状态码的目的。
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{"methods": ["GET"],"uri": "/orders","plugins": {"response-rewrite": {"status_code": 201,"body": "{\"code\":\"ok\",\"message\":\"new json body\"}","vars":[[ "status","==",200 ]]}},"upstream": {"type": "roundrobin","nodes": {"127.0.0.1:80": 1}}
}'
例如,这个例子表示将请求 /orders 路径的 API 中响应为 200 的状态的请求修改为 201。 APISIX 支持非常丰富的插件,期待你去挖掘更多的玩法。
总结
本文详细说明了什么是 API,什么是 RESTful API 以及其最佳实践。另外还介绍了如何通过 APISIX 来实现业务逻辑和安全逻辑分离,如何使用 APISIX 在不改动原有业务代码的情况下将历史 API 服务更加 RESTful。希望本文对你了解 RESTful API 有所帮助,也欢迎你来 GitHub 一起玩耍。
相关文章:
RESTful API 为何成为顶流 API 架构风格?
作者孙毅,API7.ai 技术工程师,Apache APISIX Committer 万物互联的世界充满着各式各样的 API ,如何统筹规范 API 至关重要。RESTful API 是目前世界上最流行的 API 架构风格之一,它可以帮助你实现客户端与服务端关注点分离&#x…...
Python基础知识点汇总(列表)
列表的含义 列表由一系列按特定顺序排列的元素组成,是Python中内置的可变序列。 **注:**列表的所有元素放在中括号[]中,相邻的两个元素用逗号分隔; 可将整数、实数、字符串、列表、元组等任何类型的内容放到列表中,且同一列表的元素类型可以不同。 列表的创建和删除 1.…...
新的一年软件测试行业的趋势能够更好?
如果说,2022年对于全世界来说,都是一场极大的挑战的话;那么,2023年绝对是机遇多多的一年。众所周知,随着疫情在全球范围内逐步得到控制,无论是国际还是国内的环境,都会呈现逐步回升的趋势&#…...
Threejs中的Shadow Mapping(阴影贴图)
简而言之,步骤如下: 1.从灯光位置视点(阴影相机)创建深度图。 2.从相机的位置角度进行屏幕渲染,在每个像素点,比较由阴影相机的MVP矩阵计算的深度值和深度图的值的大小,如果深度图值小的话&…...
本质安全设备标准(IEC60079-11)的理解(四)
本质安全设备标准(IEC60079-11)的理解(四) 对于标准中“Separation”的理解 IEC60079-11使用了较长的篇幅来说明设计中需要考虑到的各种间距, 这也从一定程度上说明了间距比较重要,在设计中是需要认真考虑…...
(record)QEMU安装最小linux系统——TinyCore(命令行版)
文章目录QEMU安装最小linux系统——TinyCore参考QEMU使用qemu创建tinycore虚拟机再次启动文件保存QEMU安装最小linux系统——TinyCore 简单记录安装过程和记录点 参考 [原创] qemu 与 Tiny Core tinycore的探索 QEMU qemu不多介绍,这里是在WSL2上安装的linux版…...
C++中的cast类型转换
reinterpret_cast用法:reinpreter_cast<type-id> (expression)type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。这个操作符能够在非相关的类型之间转换。操作结果…...
西瓜数据集读取的详细解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…...
Mac开发环境配置
一、mac 安装homebrew 1. 必要性 homebrew可以通过bash命令快速安装配置开发环境,并且在大多数情况下可以实现环境的自动配置。(一键安装配置) 2. 收益 节省开发环境工具配置时间,提高人效。 3. 安装步骤 打开mac终端…...
概率论面试题1:玫瑰花
概率论面试题 1. 一个活动,n个女生手里拿着长短不一的玫瑰花,无序的排成一排,一个男生从头走到尾,试图拿更长的玫瑰花,一旦拿了一朵就不能再拿其他的,错过了就不能回头,问最好的策略࿱…...
【DGL】图分类
目录概述数据集定义Data LoaderDGL中的batched graph定义模型训练参考概述 除了节点级别的问题——节点分类、边级别的问题——链接预测之外,还有整个图级别的问题——图分类。经过聚合、传递消息得到节点和边的新的表征后,映射得到整个图的表征。 数据…...
时间复杂度的计算(2023-02-10)
时间复杂度的计算 时间复杂度的计算分为三大类:一层循环、二层循环和多层循环。 一层循环 1.找出循环趟数t及每轮循环i的变化值 2.确立循环停止的条件 3.得出t与i之间的关系 4.联立两式,得出结果 eg: void fun(int n) {int i0;while (i*i*i<n)i;…...
测试开发之Django实战示例 第六章 追踪用户行为
第六章 追踪用户行为在之前的章节里完成了小书签将外站图片保存至本站的功能,并且实现了通过jQuery发送AJAX请求,让用户可以对图片进行喜欢/不喜欢操作。这一章将学习如何创建一个用户关注系统和创建用户行为流数据,还将学习Django的信号框架…...
红米9a手动root方法
简介 已知红米6A/6/9/9A/9C/10A机器都可以快速解锁BL,无任何变砖风险 并且秒解锁BL后和官方解锁一样,无任何其他不良影响。推荐大家使用官网解锁,需要等待7天。 BootLoader BootLoader是在操作系统内核运行之前运行的一段小程序。其实…...
Open3D 点云最小二乘法拟合平面(剔除噪声,Python版本)
除了诱惑之外,我可以抵抗任何事物。 ----王尔德 文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 这个算法的思路很简单,就是通过剔除一些异常点来拟合更为合适的平面,具体过程如下所示: 1、首先使用最小二乘法拟合一个平面系数的初值。 2、计算所有有效点到拟合…...
【SpringBoot】简述springboot项目启动数据加载内存中的三种方法
一、前言一般来说,SpringBoot工程环境配置放在properties文件中,启动的时候将工程中的properties/yaml文件的配置项加载到内存中。但这种方式改配置项的时候,需要重新编译部署,考虑到这种因素,今天介绍将配置项存到数据…...
【一文速通】各种机器学习算法的特点及应用场景
近邻 (Nearest Neighbor)KNN算法的核心思想是,如果一个样本在特征空间中的K个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定…...
多传感器融合定位十四-基于图优化的定位方法
多传感器融合定位十四-基于图优化的定位方法1. 基于图优化的定位简介1.1 核心思路1.2 定位流程2. 边缘化原理及应用2.1 边缘化原理2.2 从滤波角度理解边缘化3. 基于kitti的实现原理3.1 基于地图定位的滑动窗口模型3.2 边缘化过程4. lio-mapping 介绍4.1 核心思想4.2 具体流程4.…...
PHP基于TCPDF第三方类生成PDF文件
最近在研发招聘的系统 遇到了这个问题 转换pdf 折腾了很久 分享一下PHP基于TCPDF第三方类生成PDF文件最近遇到一个需求,需要根据数据库的字段生成表格式的PDF文件并发送邮箱第一步、我们先去官网上面去下载tcpdf的类:http://www.tcpdf.org/或者是从githu…...
SpringCloud(19):Sentinel定义资源的方式
Sentinel除了基本的定义资源的方式之外,还有其他的定义资源的方式,具体如下: 抛出异常的方式定义资源返回布尔值方式定义资源异步调用支持注解方式定义资源主流框架的默认适配1 抛出异常的方式定义资源 Sentinel中的SphU包含了try-catch风格的API。用这种方式,当资源发生了…...
前端 ES6 之 Promise 实践应用与控制反转
Promise 主要是为解决程序异步处理而生的,在现在的前端应用中无处不在,已然成为前端开发中最重要的技能点之一。它不仅解决了以前回调函数地狱嵌套的痛点,更重要的是它提供了更完整、更强大的异步解决方案。 同时 Promise 也是前端面试中必不…...
LightGBM
目录 1.LightGBM的直方图算法(Histogram) 直方图做差加速 2.LightGBM得两大先进技术(GOSS&EFB) 2.1 单边梯度抽样算法(GOSS) 2.2 互斥特征捆绑算法(EFB) 3.LightGBM得生长策略(leaf-wise) 通过与xgboost对比,在这里列出lgb新提出的几个方面的技术 1.Ligh…...
Science:北京脑研究中心李莹实验室揭示性满足感的分子机制
短暂的社交经历(例如,性经历)可导致内部状态的长期变化并影响社会行为,如交配、攻击。例如,在成功交配射精后,许多物种迅速表现出对交配倾向的抑制有数小时、数天或更长时间,这种效应称为性满足…...
Element UI框架学习篇(三)
Element UI框架学习篇(三) 实现简单登录功能(不含记住密码) 1 准备工作 1.1 在zlz包下创建dto包,并创建userDTO类(传输对象) package com.zlz.dto;import lombok.Data;/* DTO 数据传输对象 用户表的传输对象 调用控制器传参使用 VO 控制器返回的视图对象 与页面对应 PO 数据…...
尚硅谷的尚融宝项目
先建立一个Maven springboot项目 进来先把src删掉,因为是一个父项目,我们删掉src之后,pom里配置的东西,也能给别的模块使用。 改一下springboot的版本号码 加入依赖和依赖管理: <properties><java.versi…...
12 Day:内存管理
前言:今天我们要完成我们操作系统的内存管理,以及一些数据结构和小组件的实现,在此之前大家需要了解我们前几天一些重要文件的内存地址存放在哪,以便我们更好的去编写内存管理模块 一,实现ASSERT断言 不知道大家有没有…...
linux基本功系列之lsof命令实战
文章目录前言一. lsof命令介绍二. 语法格式及常用选项三. 参考案例3.1 显示系统打开的文件3.2 查找某个文件相关的进程3.3 列出某个用户打开的文件信息3.4 列出某个程序进程所打开的文件信息3.5 查看某个进程号打开的文件3.6 列出所有的网络连接3.7 列出谁在使用某个端口3.8 恢…...
基础篇:02-SpringCloud概述
1.SpringCloud诞生 基于前面章节,我们深知微服务已成为当前开发的主流技术栈,但是如dubbo、zookeeper、nacos、rocketmq、rabbitmq、springboot、redis、es这般众多技术都只解决了一个或一类问题,微服务并没有一个统一的解决方案。开发人员或…...
【软件测试】软件测试工作上95%会遇到的问题,你遇到多少?
目录:导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜)前言 1、测试负责人要进行…...
4.5.4 LinkedList
文章目录1.特点2.常用方法3.练习:LinkedList测试1.特点 链表,两端效率高,底层就是链表实现的 List接口的实现类,底层的数据结构为链表,内存空间是不连续的 元素有下标,有序允许存放重复的元素在数据量较大的情况下,查询慢&am…...
为什么不自己做购物网站/赣州seo
2017-08-19 主要内容:CPU和GPU介绍,几种深度学习框架的介绍 1.CPU和GPU CPU一般核数目比较少,适合做通用的计算,速度比较快,共享系统的内存 GPU一般单个核心的速度比较慢,但是核心数目很多,几千…...
深圳做网站公司有哪些/seo网站优化推广教程
转自:https://www.cnblogs.com/whiteMu/p/5378747.html 一、display:box; 在元素上设置该属性,可使其子代排列在同一水平上,类似display:inline-block;。 二、可在其子代设置如下属性 前提:使用如下属性,必须在父代设置…...
怎么在国外网站开发客户/怎么做好销售
近日服务器上的运行的一个站点经常性出现500错误。查了下服务器负载,负载正常。而后查询了下nginx记录的站点运行错误日志,发现提示Too many open files。因为站点静态文件居多,而且http请求结束后,打开的文件描述符会被自动关闭&…...
聊城手机网站建设费用/不需要验证码的广告平台
摘要vue和axios都可以使用es6-promise来实现f1().then(f2).then(f3)这样的连写形式,es6-promise其实现代浏览器已经支持,无需加载外部文件。由于promise写法明显由于传统写法,已经越来越被高级程序采用,不懂promise就没法看高级程…...
网站关键词优化报价/怎么开展网络营销推广
1、mongodb安装好后第一次进入是不需要密码的,也没有任何用户,通过shell命令可直接进入,cd到mongodb目录下的bin文件夹,执行命令./mongo即可运行如下:[rootnamenode mongodb]# ./bin/mongo MongoDB shell version: 1.8…...
个人直播网站怎么做/百度搜索广告价格
L1-083 谁能进图书馆 为了保障安静的阅读环境,有些公共图书馆对儿童入馆做出了限制。例如“12 岁以下儿童禁止入馆,除非有 18 岁以上(包括 18 岁)的成人陪同”。现在有两位小/大朋友跑来问你,他们能不能进去ÿ…...