diff --git a/docs/zh/latest/config.json b/docs/zh/latest/config.json index 2e48f06532a6..2ad3eaac2454 100644 --- a/docs/zh/latest/config.json +++ b/docs/zh/latest/config.json @@ -29,7 +29,9 @@ "tutorials/observe-your-api", "tutorials/health-check", "tutorials/client-to-apisix-mtls", - "tutorials/keycloak-oidc" + "tutorials/keycloak-oidc", + "tutorials/manage-api-consumers", + "tutorials/cache-api-responses" ] }, { diff --git a/docs/zh/latest/tutorials/cache-api-responses.md b/docs/zh/latest/tutorials/cache-api-responses.md new file mode 100644 index 000000000000..c95f99e81684 --- /dev/null +++ b/docs/zh/latest/tutorials/cache-api-responses.md @@ -0,0 +1,223 @@ +--- +title: API 响应缓存 +keywords: + - API 网关 + - Apache APISIX + - 缓存 + - 性能 +description: This tutorial will focus primarily on handling caching at the API Gateway level by using Apache APISIX API Gateway and you will learn how to use proxy-caching plugin to improve response efficiency for your Web or Microservices API. +--- + + + +本教程将主要介绍如何在 **API 网关** 级别进行缓存处理,使用 **Apache APISIX API 网关**,你将学习如何使用 **proxy-cache** 插件来提升 Web 或微服务 API 的响应效率。 + +**本次教程涵盖的内容概览:** + +* API 网关中的缓存 +* 关于 [Apache APISIX API 网关](https://apisix.apache.org/zh/docs/apisix/getting-started/) +* 运行演示项目 [apisix-dotnet-docker](https://github.com/Boburmirzo/apisix-dotnet-docker) +* 配置 [Proxy Cache](https://apisix.apache.org/zh/docs/apisix/plugins/proxy-cache/) 插件 +* 验证代理缓存功能 + +## 通过缓存提升性能 + +在构建 API 时,你希望保持其简单且高效。当并发请求需要访问相同数据量增加时,你可能会遇到一些问题,从而考虑引入 **缓存**: + +* 某些 API 请求存在延迟,明显影响用户体验。 +* 从数据库获取数据响应时间过长。 +* API 的高吞吐量可能威胁到其可用性。 +* 网络故障导致频繁访问的 API 信息获取失败。 + +## API 网关中的缓存 + +[缓存](https://zh.wikipedia.org/wiki/%E7%BC%93%E5%AD%98)能够存储并获取网络请求及其对应的响应。在 Web 应用中,缓存可以发生在不同层级: + +* 边缘缓存或 CDN +* 数据库缓存 +* 服务器缓存(API 缓存) +* 浏览器缓存 + +**反向代理缓存(Reverse Proxy Caching)** 是另一种缓存机制,通常在 **API 网关** 内部实现。它可以减少对后端接口的调用次数,并通过缓存上游响应来提高 API 请求的延迟表现。如果 API 网关缓存中存在请求资源的最新副本,它会直接使用该副本响应请求,而无需访问后端服务。如果未命中缓存,请求将转发到目标上游服务(后端服务)。 + +## Apache APISIX API 网关代理缓存 + +借助 **Apache APISIX**,你可以使用 [proxy-cache](https://apisix.apache.org/zh/docs/apisix/plugins/proxy-cache/) 插件为 API 启用缓存,从而缓存 API 端点的响应并提升性能。该插件可以与其他插件组合使用,目前支持基于磁盘的缓存。 + +要缓存的数据可以通过 **responseCodes**、**requestModes** 进行过滤,也可以使用 **noCache** 和 **cacheByPass** 属性进行更复杂的过滤。你还可以在插件配置中指定缓存的过期时间或内存容量。更多配置项请参考 `proxy-cache` 插件的 [属性说明](https://apisix.apache.org/zh/docs/apisix/plugins/proxy-cache/)。 + +有了这些基础,我们接下来将通过一个例子演示如何使用 **Apache APISIX** 的 `proxy-cache` 插件,并将其应用于 **ASP.NET Core Web API** 的单个端点。 + +## 运行演示项目 + +到目前为止,我假设你已经启动并运行了演示项目 [apisix-dotnet-docker](https://github.com/Boburmirzo/apisix-dotnet-docker)。你可以在 **GitHub** 上查看完整源码,以及如何通过 **Docker CLI** 构建多容器 **APISIX** 的说明。 + +在 **ASP.NET Core 项目** 中,有一个简单的 API,用于从服务层获取所有产品列表,位于 [ProductsController.cs](https://github.com/Boburmirzo/apisix-dotnet-docker/blob/main/ProductApi/Controllers/ProductsController.cs) 文件中。 + +假设这个产品列表通常每天只更新一次,而该端点每天需要处理数十亿次请求来部分或全部获取产品列表。在这种场景下,使用 `proxy-cache` 插件进行 API 缓存将非常有用。为了演示的目的,我们仅为 `GET` 方法启用缓存。 + +> 理想情况下,`GET` 请求应该默认是可缓存的——除非出现特殊条件。 + +## 配置 Proxy Cache 插件 + +现在,让我们开始在项目的 **Apache APISIX 声明式配置文件 `config.yaml`** 中添加 `proxy-cache` 插件。由于在当前项目中,我们还没有注册本次演示要使用的插件,因此需要将 `proxy-cache` 插件名称添加到插件列表末尾: + +```yaml +plugins: + - http-logger + - ip-restriction + … + - proxy-cache +``` + +如果你需要指定缓存相关参数(如 **disk_size**、**memory_size**),也可以在同一个文件中添加缓存配置,例如: + +```yaml +proxy_cache: + cache_ttl: 10s # 如果上游未指定缓存时间,则使用默认缓存时间 + zones: + - name: disk_cache_one # 缓存名称。管理员可以在 Admin API 中按名称指定使用哪个缓存 + memory_size: 50m # 用于存储缓存索引的共享内存大小 + disk_size: 1G # 用于存储缓存数据的磁盘大小 + disk_path: "/tmp/disk_cache_one" # 缓存数据存储路径 + cache_levels: "1:2" # 缓存的层级结构 +``` + +接下来,我们可以直接运行 `apisix reload` 命令来重新加载最新的插件代码,而无需重启 Apache APISIX。重新加载新插件的命令如下: + +```shell +curl http://127.0.0.1:9180/apisix/admin/plugins/reload -H "X-API-KEY: $admin_key" -X PUT +``` + +然后,我们运行两个 curl 命令来为 `/api/products` 端点配置 **Upstream** 和 **Route**。首先,创建一个示例 Upstream(也就是我们的 API 服务器): + +```shell +curl "http://127.0.0.1:9180/apisix/admin/upstreams/1" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PUT -d ' +{ + "type": "roundrobin", + "nodes": { + "productapi:80": 1 + } +}' +``` + +接下来,我们为 `/api/products` 添加一个具备缓存能力的路由,通过在 `plugins` 属性中设置 `proxy-cache` 插件,并通过 **upstream_id** 引用上游服务,将请求转发到 API 服务器: + +```shell +curl "http://127.0.0.1:9180/apisix/admin/routes/1" -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -X PUT -d '{ + "name": "Route for API Caching", + "methods": [ + "GET" + ], + "uri": "/api/products", + "plugins": { + "proxy-cache": { + "cache_key": [ + "$uri", + "-cache-id" + ], + "cache_bypass": [ + "$arg_bypass" + ], + "cache_method": [ + "GET" + ], + "cache_http_status": [ + 200 + ], + "hide_cache_headers": true, + "no_cache": [ + "$arg_test" + ] + } + }, + "upstream_id": 1 +}' +``` + +如上配置所示,我们定义了一些插件属性,表示只缓存 **GET 方法的成功响应(HTTP 200)**。 + +## 验证 Proxy Cache 功能 + +最后,我们可以测试代理缓存是否按预期工作。 + +我们将向 `/api/products` 路径发送多次请求,每次都应收到 `HTTP 200 OK` 响应。然而,响应头中的 `Apisix-Cache-Status` 会显示 **MISS**,表示当请求第一次访问路由时,该响应尚未缓存。此时,如果再次发送请求,你会看到响应已被缓存,`Apisix-Cache-Status` 显示 **HIT**。 + +首先,发送初始请求: + +```shell +curl http://localhost:9080/api/products -i +``` + +响应示例: + +```shell +HTTP/1.1 200 OK +… +Apisix-Cache-Status: MISS +``` + +当你再次调用该服务时,由于上一次请求已缓存,路由会返回缓存的响应: + +```shell +HTTP/1.1 200 OK +… +Apisix-Cache-Status: HIT +``` + +如果在缓存的 **TTL(生存时间)** 结束后再次访问端点,你将得到: + +```shell +HTTP/1.1 200 OK +… +Apisix-Cache-Status: EXPIRED +``` + +太棒了!我们已经为 API 端点启用了缓存。 + +### 额外测试案例 + +你也可以在 **Product Controller** 代码中添加一些延迟,并测量有缓存和无缓存情况下的响应时间: + +```c# +[HttpGet] +public IActionResult GetAll() +{ + Console.Write("The delay starts.\n"); + System.Threading.Thread.Sleep(5000); + Console.Write("The delay ends."); + return Ok(_productsService.GetAll()); +} +``` + +使用 `curl` 命令测量响应时间: + +```shell +curl -i 'http://localhost:9080/api/products' -s -o /dev/null -w "Response time: %{time_starttransfer} seconds\n" +``` + +## 后续步骤 + +如我们所学,在 **Apache APISIX** 的帮助下,为 **ASP.NET Core Web API** 配置 API 响应缓存既简单又快速。它可以显著减少对端点的调用次数,并改善 API 请求的延迟表现。Apache APISIX 还提供了众多内置插件,你可以在 [插件中心](https://apisix.apache.org/plugins) 查看并根据需要使用。 + +## 推荐阅读 + +* 你可以参考 [Expose API](./protect-api.md) 学习如何发布你的第一个 API。 +* 你可以参考 [Protect API](./protect-api.md) 学习如何保护你的 API。 diff --git a/docs/zh/latest/tutorials/manage-api-consumers.md b/docs/zh/latest/tutorials/manage-api-consumers.md new file mode 100644 index 000000000000..76e7bf9836f1 --- /dev/null +++ b/docs/zh/latest/tutorials/manage-api-consumers.md @@ -0,0 +1,276 @@ +--- +title: 管理 API 消费者 +keywords: + - API 网关 + - Apache APISIX + - Rate Limit + - Consumer + - Consumer Group +description: This tutorial explains how to manage your single or multiple API consumers with Apache APISIX. +--- + + + +本教程介绍了如何使用 Apache APISIX 管理单个或多个 API 消费者(API Consumers)。 + +如今,[API](https://en.wikipedia.org/wiki/API) 使得多个系统、内部服务以及第三方应用能够轻松且安全地互联。API 消费者(API consumers)对于 API 提供方来说是最重要的利益相关者之一,因为他们与 API 及开发者门户的交互最为频繁。本文将介绍如何使用开源 API 管理解决方案 [Apache APISIX](https://apisix.apache.org/) 来管理单个或多个 API 消费者。 + +![Manage API Consumers](https://static.apiseven.com/2022/11/29/6385b565b4c11.png) + +## API 消费者(API Consumers) + +API 消费者是指使用某个 API 的用户,但他们并不会专门为该 API 开发应用。换句话说,API 消费者就是 API 的使用者。 +例如,市场部门可能会使用 [Facebook API](https://developers.facebook.com/docs/) 来分析社交媒体上对特定活动的反馈,他们会在需要时向提供的 API 发送独立且不定期的请求。 + +一个 [API 管理](https://en.wikipedia.org/wiki/API_management) 解决方案需要能够识别谁是 API 的消费者,以便针对不同的消费者配置不同的规则。 + +## Apache APISIX 中的消费者(Consumers) + +在 Apache APISIX 中,[Consumer 对象](https://apisix.apache.org/zh/docs/apisix/terminology/consumer/) 是 API 消费者访问通过 [API 网关(API Gateway)](https://apisix.apache.org/zh/docs/apisix/terminology/api-gateway/) 发布的 API 的主要方式。 +当不同的消费者请求同一个 API,而你需要针对不同消费者执行不同的 [插件(Plugin)](https://apisix.apache.org/zh/docs/apisix/terminology/plugin/) 或 [上游(Upstream)](https://apisix.apache.org/zh/docs/apisix/terminology/upstream/) 配置时,Consumer 概念会非常有用。 + +通过 Apache APISIX API 网关发布 API 后,可以轻松使用消费者密钥(consumer key,也称订阅密钥 subscription key)来保护 API 访问。 +需要使用已发布 API 的开发者必须在调用这些 API 的 `HTTP` 请求中包含有效的订阅密钥。若订阅密钥无效,API 网关会立即拒绝请求,而不会将其转发到后端服务。 + +消费者可以关联不同的作用范围:按插件、所有 API 或单个 API。 +在 API 网关中,结合插件使用消费者对象可以实现多种场景: + +1. 为不同消费者启用不同的认证方式。 + 当消费者尝试通过不同认证机制(如 [API key](https://apisix.apache.org/zh/docs/apisix/plugins/key-auth/)、[Basic](https://apisix.apache.org/zh/docs/apisix/plugins/basic-auth/)、或基于 [JWT](https://apisix.apache.org/zh/docs/apisix/plugins/jwt-auth/) 的认证)访问 API 时,这种机制非常有用。 +2. 限制特定消费者对 API 资源的访问。 +3. 根据消费者将请求路由到相应的后端服务。 +4. 定义数据消费的速率限制。 +5. 分析单个消费者或消费者子集的数据使用情况。 + +## Apache APISIX Consumer 示例 + +下面我们来看一个示例,演示如何结合 [key-auth](https://apisix.apache.org/zh/docs/apisix/plugins/key-auth/) 认证插件(API Key)与 [limit-count](https://apisix.apache.org/zh/docs/apisix/plugins/limit-count/) 插件,为单个消费者或一组消费者配置限流策略。 + +在本示例中,我们将使用一个基于 [ASP.NET Core Web API](https://learn.microsoft.com/en-us/aspnet/core/?view=aspnetcore-7.0) 的 [示例项目](https://github.com/Boburmirzo/apisix-api-consumers-management),该项目包含一个简单的 `GET` 接口,用于获取商品列表。 +项目的运行方式可在其 [README 文件](https://github.com/Boburmirzo/apisix-api-consumers-management#readme) 中找到详细说明。 + +### 为单个消费者启用限流(Rate Limiting) + +假设此时示例项目已经启动运行。 +要将消费者对象与上述两个插件配合使用,我们需要执行以下步骤: + +1. 创建一个新的 **Consumer(消费者)**。 +2. 为该消费者配置认证插件 `key-auth` 和限流插件 `limit-count`。 +3. 创建新的 **Route(路由)**,并设置路由规则(如有需要)。 +4. 为该路由启用 `key-auth` 插件配置。 + +以上步骤只需通过两条 [curl 命令](https://en.wikipedia.org/wiki/CURL) 调用 APISIX 的 [Admin API](https://apisix.apache.org/zh/docs/apisix/admin-api/) 即可完成。 + +第一条命令创建一个启用了 API Key 认证的 **新消费者**,并配置限流规则: +该消费者在 60 秒内最多只能调用产品 API 两次。 + +```shell +curl http://127.0.0.1:9180/apisix/admin/consumers -H "X-API-KEY: $admin_key" -X PUT -d ' +{ + "username":"consumer1", + "plugins":{ + "key-auth":{ + "key":"auth-one" + }, + "limit-count":{ + "count":2, + "time_window":60, + "rejected_code":403, + "rejected_msg":"Requests are too many, please try again later or upgrade your subscription plan.", + "key":"remote_addr" + } + } +}' +``` + +接下来,我们定义一个新的 **Route(路由)** 与 **Upstream(上游)**, +使得所有到达网关端点 `/api/products` 的请求在通过认证后,都会被转发到示例项目的产品服务。 + +```shell +curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d ' +{ + "name": "Route for consumer request rate limiting", + "methods": [ + "GET" + ], + "uri": "/api/products", + "plugins": { + "key-auth": {} + }, + "upstream": { + "type": "roundrobin", + "nodes": { + "productapi:80": 1 + } + } +}' +``` + +在此配置下,Apache APISIX 将正常处理前两次请求, +但在相同的 60 秒时间窗口内的 **第三次请求** 将返回一个 `403` HTTP 状态码。 + +```shell +curl http://127.0.0.1:9080/api/products -H 'apikey: auth-one' -i +``` + +如果在 60 秒内连续调用三次接口,示例输出如下: + +```shell +HTTP/1.1 403 Forbidden +Content-Type: text/plain; charset=utf-8 +Transfer-Encoding: chunked +Connection: keep-alive +Server: APISIX/2.13.1 + +{"error_msg":"Requests are too many, please try again later or upgrade your subscription plan."} +``` + +当请求次数达到阈值后,APISIX 将拒绝后续请求。 + +### 为消费者组启用限流(Rate Limiting for Consumer Groups) + +在 Apache APISIX 中,[Consumer Group(消费者组)](https://apisix.apache.org/zh/docs/apisix/terminology/consumer-group/) 对象用于管理开发者对后端服务的可见性。 +后端服务首先对特定组可见,然后组内的开发者即可查看并订阅与该组关联的产品。 + +借助消费者组,你可以为一组消费者定义多级限流策略,而无需逐个管理每个消费者。 + +典型场景包括: + +* API 商业化中的不同定价策略,例如“Basic 套餐”的消费者每分钟允许调用 50 次 API; +* 或根据用户角色(管理员、开发者、访客等)启用不同的 API 权限访问。 + +你可以通过 Apache APISIX 的管理 REST API 中的 [Consumer Group 实体](https://apisix.apache.org/zh/docs/apisix/admin-api/#consumer-group) 来创建、更新、删除和管理消费者组。 + +#### Consumer groups 示例 + +为了演示,我们将分别为 **Basic(基础)** 和 **Premium(高级)** 两种套餐创建两个消费者组(Consumer Group)。 +我们可以为每个组添加一个或两个消费者,并通过 `rate-limiting` 插件来控制来自不同消费者组的流量。 + +要在限流场景中使用消费者组,你需要执行以下步骤: + +* 创建一个或多个启用了 `limit-count` 插件的消费者组。 +* 创建消费者(Consumers),并将它们分配到对应的组中。 + +下面的两条 `curl` 命令用于分别创建名为 `basic_plan` 和 `premium_plan` 的消费者组: + +**创建 Basic Plan(基础套餐)的消费者组** + +```shell +curl http://127.0.0.1:9180/apisix/admin/consumer_groups/basic_plan -H "X-API-KEY: $admin_key" -X PUT -d ' +{ + "plugins": { + "limit-count": { + "count": 2, + "time_window": 60, + "rejected_code": 403, + "group": "basic_plan" + } + } +}' +``` + +**创建 Premium Plan(高级套餐)的消费者组** + +```shell +curl http://127.0.0.1:9180/apisix/admin/consumer_groups/premium_plan -H "X-API-KEY: $admin_key" -X PUT -d ' +{ + "plugins": { + "limit-count": { + "count": 200, + "time_window": 60, + "rejected_code": 403, + "group": "premium_plan" + } + } +}' +``` + +在上述步骤中,我们为 **Basic Plan** 设置了限流规则:每 60 秒内仅允许 **2 次请求**; +而 **Premium Plan** 则允许在相同时间窗口内执行 **200 次 API 请求**。 + +**创建并将第一个消费者加入 Basic 组** + +```shell +curl http://127.0.0.1:9180/apisix/admin/consumers -H "X-API-KEY: $admin_key" -X PUT -d ' +{ + "username": "consumer1", + "plugins": { + "key-auth": { + "key": "auth-one" + } + }, + "group_id": "basic_plan" +}' +``` + +**创建并将第二个消费者加入 Premium 组** + +```shell +curl http://127.0.0.1:9180/apisix/admin/consumers -H "X-API-KEY: $admin_key" -X PUT -d ' +{ + "username": "consumer2", + "plugins": { + "key-auth": { + "key": "auth-two" + } + }, + "group_id": "premium_plan" +}' +``` + +**创建并将第三个消费者加入 Premium 组** + +```shell +curl http://127.0.0.1:9180/apisix/admin/consumers -H "X-API-KEY: $admin_key" -X PUT -d ' +{ + "username": "consumer3", + "plugins": { + "key-auth": { + "key": "auth-three" + } + }, + "group_id": "premium_plan" +}' +``` + +之后,我们可以验证限流效果: +属于 **Basic Plan** 组的第一个消费者 `consumer1` 在 1 分钟内调用 API 超过 2 次后,将收到 **403 HTTP 状态码错误**; +而属于 **Premium Plan** 组的其他两个消费者则可继续请求,直到达到各自的请求上限。 + +你可以通过在请求头中更换认证密钥来执行以下命令进行测试: + +```shell +curl -i http://127.0.0.1:9080/api/products -H 'apikey: auth-one' +``` + +```shell +curl -i http://127.0.0.1:9080/api/products -H 'apikey: auth-two' +``` + +```shell +curl -i http://127.0.0.1:9080/api/products -H 'apikey: auth-three' +``` + +请注意,你还可以在任意时刻将消费者添加到或移出消费者组,并启用其他内置插件。 + +## 更多教程 + +阅读我们的其他 [教程](./expose-api.md),以了解更多有关 **API 管理(API Management)** 的内容。