您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

如何循序渐进地管理RESTful API的生命周期?

时间:2022-08-29 15:43:17  来源:  作者:鸨哥学Java

设计一个直观且用户友好的RESTful API往往是一项艰巨的工作。而对于初次尝试规划和管理API生命周期的新手开发者而言,尤为如此。下面,我将以简单示例的形式,和您探讨如何循序渐进地管理RESTful API的生命周期。

 

初始阶段

让我们首先来看一个典型的Hello应用代码的示例:

> curl http://org. apisix/hello
Hello world
> curl http://org. apisix/hello/Joe
Hello Joe

如下图所示,我们不必了解其底层技术,只需专注其API部分即可。

 

采用API网关

首先也是最关键的一步:禁止将应用直接暴露到互联网上,并在前端建立一个API网关。维基百科是这样定义API网关的:作为一个API的服务器前端,它能够收到各种API请求,并通过实施节流和安全策略,将请求传递给后端服务,进而将响应回传给请求者。

网关通常包括一个用于编排和修改请求与响应转换引擎。同时,网关还可以提供诸如:收集分析数据、提供缓存、支持身份验证、授权、安全审计以及合规检查等功能。当然,如果您不太熟悉API网关的概念,也可以直接把它理解为一个更高级别的反向代理。在此,我将使用 Apache APISIX​ ​,您也可以使用自己熟悉的网关。

为了暴露网关,您需要更新指向网关的DNS记录,并向外广播。您既可以等待一段时间让其自动更新,也可以通过​ ​dnschecker​ ​来加速这个过程。

我使用APISIX创建了一个将HTTP请求发送到网关的路由(route,请参见如下代码段)。

curl http://apisix:9080/apisix/admin/routes/1 -H 'X-API-KEY: xyz' -X PUT -d ' # 1-2
{
  "name": "Direct Route to Old API",               # 3
  "methods": ["GET"],                              # 4
  "uris": ["/hello", "/hello/", "/hello/*"],       # 5
  "upstream": {                                    # 6
    "type": "roundrobin",                          # 8
    "nodes": {
      "oldapi:8081": 1                             # 7
    }
  }
}'

注释:

1. APISIX会分配一个自动生成的ID(您也可以使用现成的)。在此,我使用现成的,并使用put将它传递给URL - 1。

2. 通过API key来更新路由。

3. 虽然我们不一定需要命名路由,但它能够让我们更好地对其有所了解。

4. 针对路由的HTTP方法数组。

5. 针对路由的URL数组。

6. 指明后端应用的上游(upstream)。在本例中,即为Hello World API。

7. 各个节点的Hashmap都自带有权重。显然,权重只有存在多个节点时才有意义。

8. 针对多个节点配置均衡算法。

 

如上图所示,您可以通过如下方式查询网关,并得到相同的结果:

> curl http://org. apisix/hello
Hello world
> curl http://org. apisix/hello/Joe
Hello Joe

API的版本

开发一个API往往意味着会出现其多个版本共存的情况。我们可以用如下三种方式给API编制版本:

  • 查询参数:

curl http://org. apisix/hello?version=1

curl http://org. apisix/hello?version=2

  • 标头:

curl -H 'Version: 1' http://org. apisix/hello

curl -H 'Version: 2' http://org. apisix/hello

  • 路径:

curl http://org. apisix/v1/hello

curl http://org. apisix/v2/hello

在此,我将使用目前广为采用的基于路径的版本编制方法。当然,APISIX也支持其他两种方式。

在前文中,我们创建了一个包含上游信息的路由。同时,APISIX也允许我们创建一个带有专属ID的上游,以重用其多个路由:

curl http://apisix:9080/apisix/admin/upstreams/1 -H 'X-API-KEY: xyz' -X PUT -d ' # 1
{
  "name": "Old API",                                                             # 2
  "type": "roundrobin",
  "nodes": {
    "oldapi:8081": 1
  }
}'

注释:

1. 使用upstreams路径

2. 针对新的上游的有效载荷

由于上游只知道/hello,不知道/v1/hello,因此在转发至上游之前,我们仍需要重写发往网关的查询。APISIX可以通过插件来实现此类转换和过滤。下面,让我们创建一个用于重写路径的插件配置:

curl http://apisix:9080/apisix/admin/plugin_configs/1 -H 'X-API-KEY: xyz' -X PUT -d ' # 1
{
  "plugins": {
    "proxy-rewrite": {                                        # 2
      "regex_uri": ["/v1/(.*)", "/$1"]                        # 3
    }
  }
}'

注释:

1. 使用plugin-configs路径

2. 使用​ ​proxy-rewrite​ ​插件

3. 删除版本的前缀

现在我们就可以通过如下代码段,创建有版本的路由,以引导新创建的上游和插件配置:

curl http://apisix:9080/apisix/admin/routes/2 -H 'X-API-KEY: xyz' -X PUT -d '  # 1
{
  "name": "Versioned Route to Old API",
  "methods": ["GET"],
  "uris": ["/v1/hello", "/v1/hello/", "/v1/hello/*"],
  "upstream_id": 1,
  "plugin_config_id": 1
}'

下面展示了新路由的逻辑图。

 

在此,我们已配置了有版本和非版本的两个路由:

> curl http://org. apisix/hello
Hello world
> curl http://org. apisix/v1/hello
Hello world

将用户从非版本路径迁移到有版本路径

虽然我们给API编制了版本,但是用户可能仍会使用旧的、非版本的API。毕竟,我们肯定不能在用户不知情时就删除掉旧的路由,而只能通过HTTP的301状态代码,让用户知道资源已经从http://org.apisix/hello迁移到了

http://org.apisix/v1/hello。如下代码段展示了​ ​如何通过配置重定向插件​ ​来初始化路由:

curl http://apisix:9080/apisix/admin/routes/1 -H 'X-API-KEY: xyz' -X PATCH -d '
{
  "plugins": {
    "redirect": {
      "uri": "/v1$uri",
      "ret_code": 301
    }
  }
}'

 

其运行结果如下:

>curl http://apisix. org/hello
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>openresty</center>
</body>
</html>
>curl -L apisix:9080/hello                     # 1
Hello world

注释:

1. -L选项后面跟着重定向

根据规则,用户要么透明地使用到了新的端点,要么收到301的状态提示,使用新的API位置。

识别用户

您可能已经注意到,我们并不知道谁会使用我们的API。因此,为了保证API在被调用的过程中不会中断用户的使用,我选择了限制未注册的用户可调用的数量。如果他们的总量到达了该限制,我们将返回典型的HTTP 429状态消息,要求他们完成注册。

当然,目前尚无开箱即用的插件可以实现这一点。因此,我在APISIX中引入Lua引擎,并用Lua编写出了相应的插件。您可以通过Github的链接

--https://github.com/nfrankel/evolve-apis/blob/master/unauth-limit-plugin/src/unauth-limit.lua,来浏览其源代码。当然,您也可以使用Python/ target=_blank class=infotextkey>Python、WebAssembly或任何基于JVM的语言,来编写自己的插件。

我将通过如下步骤来完成插件的加载:

1. 配置APISIX使用的目录:

apisix: extra_lua_path:/opt/apisix/.lua ?”

注意:APISIX可以使用位于/opt/apisix/文件夹下的任何Lua脚本。

2. 加载插件:

由于APISIX支持热重载,因此它可以在无需重新启动的情况下添加额外的插件。

curl http://apisix:9080/apisix/admin/plugins/reload -H 'X-API-KEY: xyz' -X PUT

3. 给现有插件的配置打补丁:

最后,我们需要为插件本身更新专属的配置:

curl http://apisix:9080/apisix/admin/plugin_configs/1 -H 'X-API-KEY: xyz' -X PATCH -d '
{
  "plugins": {
    "proxy-rewrite": {                                # 1
      "regex_uri": ["/v1/(.*)", "/$1"]
    },
    "unauth-limit": {                                 # 2
      "count": 1,                                     # 3
      "time_window": 60,                              # 3
      "key_type": "var",                              # 4
      "key": "consumer_name",                         # 4
      "rejected_code": 429,
      "rejected_msg": "Please register at https://apisix. org/register to get your API token and enjoy unlimited calls"
    }
  }
}'

注释:

1. 我们需要重复现有的插件配置。当然,APISIX团队正在修复这个bug。

2. 指向我们的插件。

3. 对于已通过认证的用户,插件可限制每60秒超过一个调用。

4. 我会在下一节中解释到。

我们通过如下命令检查其是否能够按预期运行:

>curl apisix:9080/v1/hello
Hello world
>curl apisix:9080/v1/hello
{"error_msg":"Please register at https://apisix. org/register to get your API token and enjoy unlimited calls"}

实际上确实如此。

用户认证

接着,我们需要为消费者(consumer)角色配置一个专属的身份验证插件。目前,我们可以选用的此类身份验证插件有:API key、JWT、OpenId、LDAP、以及Keycloak等。在本例中,我们采用APISIX的​ ​key-auth​ ​插件。下面,让我们配置一个通过API key验证的消费者对象:

curl http://apisix:9080/apisix/admin/consumers -H 'X-API-KEY: xyz' -X PUT -d '
{
  "username": "johndoe",                 # 1
  "plugins": {
    "key-auth": {                        # 2
      "key": "mykey"                     # 3
    }
  }
}'

注释:

1. 消费者的ID

2. 可供使用的插件

3. 有效令牌--mykey

注意,其默认的标头为apikey,你也可以配置为其他,具体请参见key-auth插件的​ ​相关文档​ ​。

我们用如下命令来验证其是否能够按照我们的需求运行:

>curl -H 'apikey: mykey' apisix:9080/v1/hello
Hello world
>curl -H 'apikey: mykey' apisix:9080/v1/hello
Hello world

在生产环境中测试

至此,我们的改进版Hello world API便可以供用户调用了。如您所见,部署一个新的、可能包含潜在错误的应用版本,往往会给生产环境和业务营收带来负面的影响。为了尽量减少此类风险,我们可以采用金丝雀发布策略,即:先对一小部分用户推出新的软件版本,然后慢慢地扩展到生产环境中的所有用户处。如果出现了故障,那么新版本只会影响一小部分的用户群,我们能够及时回滚到旧的版本。就API网关而言,我们可以复制生产环境的流量到新的API端点上,实现在对用户几乎不产生影响的情况下,尽早发现更多的缺陷。

在此,APISIX提供了​ ​proxy-mirror插件​ ​,可向其他节点发送复制的生产环境流量。对此,我们可以对插件配置做如下更新:

curl http://apisix:9080/apisix/admin/plugin_configs/1 -H 'X-API-KEY: xyz' -X PATCH -d '
{
 "plugins": {
    "proxy-rewrite": {
      "regex_uri": ["/v1/(.*)", "/$1"]
    },
    "unauth-limit": {
      "count": 1,
      "time_window": 60,
      "key_type": "var",
      "key": "consumer_name",
      "rejected_code": 429,
      "rejected_msg": "Please register at https://apisix. org/register to get your API token and enjoy unlimited calls"
    },
    "proxy-mirror": {
      "host": "http://new. api:8082"                             # 1
    }
  }
}'

注释:

1. APISIX将发送流量到该地址上。

 

根据上图,我们可以监控和比较新和旧端点,一旦发生错误,我们便可以修复错误,并重新部署。在此,我们首先通过如下命令,创建一个指向新的API的上游:

curl http://apisix:9080/apisix/admin/upstreams/2 -H 'X-API-KEY: xyz' -X PUT -d '
{
  "name": "New API",
  "type": "roundrobin",
  "nodes": {
    "newapi:8082": 1
  }
}'

然后,我们可以使用​ ​traffic-split​ ​,来更换proxy-mirror插件:

curl http://apisix:9080/apisix/admin/plugin_configs/1 -H 'X-API-KEY: xyz' -X PATCH -d '
{
 "plugins": {
    "proxy-rewrite": {
      "regex_uri": ["/v1/(.*)", "/$1"]
    },
    "unauth-limit": {
      "count": 1,
      "time_window": 60,
      "key_type": "var",
      "key": "consumer_name",
      "rejected_code": 429,
      "rejected_msg": "Please register at https://apisix. org/register to get your API token and enjoy unlimited calls"
    },
    "traffic-split": {
      "rules": [
        {
          "weighted_upstreams": [      # 1
            {
              "upstream_id": 2,
              "weight": 1
            },
            {
              "weight": 1
            }
          ]
        }
      ]
    }
  }
}'

注释:

1. 作为演示,我们将50%的流量发送到新的API。在真实环境中,您可能只会配置少数的内部用户去使用新的端点。

curl -L -H 'apikey: mykey' apisix:9080/hello
Hello world
curl -L -H 'apikey: mykey' apisix:9080/hello
Hello world (souped-up version!)

如果一切工作正常,我们可以将逐渐增加的流量移至新的API。最终我们可以移除traffic split,将默认端点从v1重定到v2上。

弃用旧的版本

根据IETF的草案规范,我们可以基于特定的HTTP响应标头,来弃用HTTP的标头字段 (请参见

--https://tools.ietf.org/id/draft-dalal-deprecation-header-03.html)。即:在API网关的帮助下,我们可以通过配置路由,来与有待弃用和替代的版本进行通信。为此,我们将使用由APISIX提供​ ​response-rewrite​ ​,来添加额外弃用标志标头,请参见如下代码段:

curl -v http://apisix:9080/apisix/admin/plugin_configs/1 -H 'X-API-KEY: xyz' -X PATCH -d '
{
 "plugins": {
    "proxy-rewrite": {
      "regex_uri": ["/v1/(.*)", "/$1"]
    },
    "unauth-limit": {
      "count": 1,
      "time_window": 60,
      "key_type": "var",
      "key": "consumer_name",
      "rejected_code": 429,
      "rejected_msg": "Please register at https://apisix. org/register to get your API token and enjoy unlimited calls"
    },
    "response-rewrite": {
      "headers": {
        "Deprecation": "true",
        "Link": "<$scheme://apisix:$server_port/v2/hello>; rel="successor-version""
      }
    }
  }
}'
curl -v -H 'apikey: mykey' apisix:9080/v1/hello
< HTTP/1. 1 200 
< Content-Type: text/plAIn;charset=UTF-8
< Content-Length: 11
< Connection: keep-alive
< Date: Fri, 18 Feb 2022 16:33:30 GMT
< Server: APISIX/2. 12. 0
< Link: <http://apisix:9080/v2/hello>; rel="successor-version"
< Deprecation: true
< 
Hello world

小结

回顾一下,我们按照如下流程向您展示了如何通过循序渐进的过程,来管理API的整个生命周期。

1. 不要直接暴露您的API,而是在前端建立一个API网关

2. 使用路径、查询参数、以及请求标头给现有的API编制版本

3. 通过使用301状态码,将用户从无版本的端点迁移到有版本处

4. 识别和认证用户

5. 为了测试生产环境,我们先复制流量,再将小部分用户迁移到新的版本上

6. 发布新的版本

7. 通过标准响应标头来弃用旧的版本



Tags:RESTful   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
构建灵活的RESTful API:Gin框架的路由参数实战
1. 简介本文将主要介绍 Gin 框架中对于路由参数支持的特性。我们将从RESTful成为主要API设计风格出发,推导出我们在设计API时,应该同样尽量遵循该规范。基于此,我们将引出路由...【详细内容】
2023-08-11  Search: RESTful  点击:(190)  评论:(0)  加入收藏
理解并实践RESTful API设计
什么是REST?REST(Representational State Transfer,表述性状态转移)是一种用于创建网络应用程序的架构风格。自从Roy Fielding在2000年首次引入REST概念以来,它已经成为设计和构...【详细内容】
2023-05-10  Search: RESTful  点击:(439)  评论:(0)  加入收藏
如何循序渐进地管理RESTful API的生命周期?
设计一个直观且用户友好的RESTful API往往是一项艰巨的工作。而对于初次尝试规划和管理API生命周期的新手开发者而言,尤为如此。下面,我将以简单示例的形式,和您探讨如何循序渐...【详细内容】
2022-08-29  Search: RESTful  点击:(461)  评论:(0)  加入收藏
基于NodeJS的KOA2框架实现restful API网站后台
在此前写的文章“从零基础入门进行小程序开发实战”中,已经介绍过背单词的小程序,因为没有备案的服务器资源只能使用系统后台提供的缓存功能存储用户数据。缓存有大小限制,而且...【详细内容】
2021-07-27  Search: RESTful  点击:(413)  评论:(0)  加入收藏
全栈开发必备技能:构建RESTful API的13种最佳实践
Facebook、GitHub、Google以及其他许多巨头都需要一种服务和消费数据的方式。在当今的开发环境中,RESTful API仍然是服务和消费数据的最佳选择之一。 但是你是否考虑过学习行...【详细内容】
2020-08-30  Search: RESTful  点击:(216)  评论:(0)  加入收藏
一个用Java实现的超轻量级RESTful Web服务示例
通过管理一套图书的完整代码示例,来探索轻量级的 RESTful 服务。&bull; 来源:linux.cn &bull; 作者:Marty Kalin &bull; 译者:MCGA &bull;(本文字数:24337,阅读时长大约:28 分钟)Web...【详细内容】
2020-08-27  Search: RESTful  点击:(252)  评论:(0)  加入收藏
设计RESTful API的5个最佳实践
RESTful API无处不在,比任何其他API体系结构都为现代世界提供了更多支持。 根据ProgrammableWeb的研究,REST占API的80%。 这些API的构建和结构方式可以在当今竞争异常激烈的世...【详细内容】
2020-06-21  Search: RESTful  点击:(368)  评论:(0)  加入收藏
RESTful API书写规范
基于一些不错的RESTful开发组件,可以快速的开发出不错的RESTful API,但如果不了解开发规范的、健壮的RESTful API的基本面,即便优秀的RESTful开发组件摆在面前,也无法很好的理...【详细内容】
2020-01-02  Search: RESTful  点击:(387)  评论:(0)  加入收藏
RESTful 架构基础
来自:唐尤华译自:https://dzone.com/refcardz/rest-foundations-restful REST(Representational State Transfer)架构风格是一种世界观,把信息提升为架构中的一等公民。通过 R...【详细内容】
2019-10-21  Search: RESTful  点击:(776)  评论:(0)  加入收藏
后端开发必备的 RestFul API 知识
RestFul API 是每个程序员都应该了解并掌握的基本知识,我们在开发过程中设计API的时候也应该至少要满足RestFul API的最基本的要求(比如接口中尽量使用名词,使用POST 请求创建...【详细内容】
2019-08-12  Search: RESTful  点击:(1021)  评论:(0)  加入收藏
▌简易百科推荐
Netflix 是如何管理 2.38 亿会员的
作者 | Surabhi Diwan译者 | 明知山策划 | TinaNetflix 高级软件工程师 Surabhi Diwan 在 2023 年旧金山 QCon 大会上发表了题为管理 Netflix 的 2.38 亿会员 的演讲。她在...【详细内容】
2024-04-08    InfoQ  Tags:Netflix   点击:(2)  评论:(0)  加入收藏
即将过时的 5 种软件开发技能!
作者 | Eran Yahav编译 | 言征出品 | 51CTO技术栈(微信号:blog51cto) 时至今日,AI编码工具已经进化到足够强大了吗?这未必好回答,但从2023 年 Stack Overflow 上的调查数据来看,44%...【详细内容】
2024-04-03    51CTO  Tags:软件开发   点击:(7)  评论:(0)  加入收藏
跳转链接代码怎么写?
在网页开发中,跳转链接是一项常见的功能。然而,对于非技术人员来说,编写跳转链接代码可能会显得有些困难。不用担心!我们可以借助外链平台来简化操作,即使没有编程经验,也能轻松实...【详细内容】
2024-03-27  蓝色天纪    Tags:跳转链接   点击:(13)  评论:(0)  加入收藏
中台亡了,问题到底出在哪里?
曾几何时,中台一度被当做“变革灵药”,嫁接在“前台作战单元”和“后台资源部门”之间,实现企业各业务线的“打通”和全域业务能力集成,提高开发和服务效率。但在中台如火如荼之...【详细内容】
2024-03-27  dbaplus社群    Tags:中台   点击:(9)  评论:(0)  加入收藏
员工写了个比删库更可怕的Bug!
想必大家都听说过删库跑路吧,我之前一直把它当一个段子来看。可万万没想到,就在昨天,我们公司的某位员工,竟然写了一个比删库更可怕的 Bug!给大家分享一下(不是公开处刑),希望朋友们...【详细内容】
2024-03-26  dbaplus社群    Tags:Bug   点击:(5)  评论:(0)  加入收藏
我们一起聊聊什么是正向代理和反向代理
从字面意思上看,代理就是代替处理的意思,一个对象有能力代替另一个对象处理某一件事。代理,这个词在我们的日常生活中也不陌生,比如在购物、旅游等场景中,我们经常会委托别人代替...【详细内容】
2024-03-26  萤火架构  微信公众号  Tags:正向代理   点击:(11)  评论:(0)  加入收藏
看一遍就理解:IO模型详解
前言大家好,我是程序员田螺。今天我们一起来学习IO模型。在本文开始前呢,先问问大家几个问题哈~什么是IO呢?什么是阻塞非阻塞IO?什么是同步异步IO?什么是IO多路复用?select/epoll...【详细内容】
2024-03-26  捡田螺的小男孩  微信公众号  Tags:IO模型   点击:(9)  评论:(0)  加入收藏
为什么都说 HashMap 是线程不安全的?
做Java开发的人,应该都用过 HashMap 这种集合。今天就和大家来聊聊,为什么 HashMap 是线程不安全的。1.HashMap 数据结构简单来说,HashMap 基于哈希表实现。它使用键的哈希码来...【详细内容】
2024-03-22  Java技术指北  微信公众号  Tags:HashMap   点击:(11)  评论:(0)  加入收藏
如何从头开始编写LoRA代码,这有一份教程
选自 lightning.ai作者:Sebastian Raschka机器之心编译编辑:陈萍作者表示:在各种有效的 LLM 微调方法中,LoRA 仍然是他的首选。LoRA(Low-Rank Adaptation)作为一种用于微调 LLM(大...【详细内容】
2024-03-21  机器之心Pro    Tags:LoRA   点击:(12)  评论:(0)  加入收藏
这样搭建日志中心,传统的ELK就扔了吧!
最近客户有个新需求,就是想查看网站的访问情况。由于网站没有做google的统计和百度的统计,所以访问情况,只能通过日志查看,通过脚本的形式给客户导出也不太实际,给客户写个简单的...【详细内容】
2024-03-20  dbaplus社群    Tags:日志   点击:(4)  评论:(0)  加入收藏
站内最新
站内热门
站内头条