feat: Add response-cache plugin (#3061)

Co-authored-by: mirror58229 <674958229@qq.com>
This commit is contained in:
Jingze
2025-12-26 17:22:03 +08:00
committed by jingze
parent 659d136bfe
commit f342f50ca4
11 changed files with 1649 additions and 0 deletions

View File

@@ -0,0 +1,131 @@
## 简介
---
title: 通用响应缓存
keywords: [higress,response cache]
description: 通用响应缓存插件配置参考
---
## 功能说明
通用响应缓存插件,支持从请求头/请求体中提取key从响应体中提取value并缓存起来下次请求时如果请求头/请求体中携带了相同的key则直接返回缓存中的value而不会请求后端服务。
**提示**
携带请求头`x-higress-skip-response-cache: on`时,当前请求将不会使用缓存中的内容,而是直接转发给后端服务,同时也不会缓存该请求返回响应的内容
## 运行属性
插件执行阶段:`认证阶段`
插件执行优先级:`10`
## 配置说明
配置包括 缓存数据库cache配置部分以及配置缓存内容部分
## 配置说明
## 缓存服务cache
| cache.type | string | required | "" | 缓存服务类型,例如 redis |
| --- | --- | --- | --- | --- |
| cache.serviceName | string | required | "" | 缓存服务名称 |
| cache.serviceHost | string | required | "" | 缓存服务域名 |
| cache.servicePort | int64 | optional | 6379 | 缓存服务端口 |
| cache.username | string | optional | "" | 缓存服务用户名 |
| cache.password | string | optional | "" | 缓存服务密码 |
| cache.timeout | uint32 | optional | 10000 | 缓存服务的超时时间单位为毫秒。默认值是10000即10秒 |
| cache.cacheTTL | int | optional | 0 | 缓存过期时间,单位为秒。默认值是 0即 永不过期|
| cacheKeyPrefix | string | optional | "higress-response-cache:" | 缓存 Key 的前缀,默认值为 "higress-response-cache:" |
## 其他配置
| Name | Type | Requirement | Default | Description |
| --- | --- | --- | --- | --- |
| cacheResponseCode | array of number | optional | 200 | 表示支持缓存的响应状态码列表默认为200|
| cacheKeyFromHeader | string | optional | "" | 表示提取header中的固定字段的值作为缓存key配置此项时会从请求头提取key不会读取请求bodycacheKeyFromHeader和cacheKeyFromBody**非空情况下只支持配置一项**|
| cacheKeyFromBody | string | optional | "" | 配置为空时表示提取所有body作为缓存key否则按JSON响应格式从请求 Body 中基于 [GJSON PATH](https://github.com/tidwall/gjson/blob/master/SYNTAX.md) 语法提取字符串仅在cacheKeyFromHeader为空或未配置时生效 |
| cacheValueFromBodyType | string | optional | "application/json" | 表示缓存body的类型命中cache时content-type会返回该值默认为"application/json" |
| cacheValueFromBody | string | optional | "" | 配置为空时表示缓存所有body当cacheValueFromBodyType为"application/json"时,支持从响应 Body 中基于 [GJSON PATH](https://github.com/tidwall/gjson/blob/master/SYNTAX.md) 语法提取字符串 |
其中缓存key的拼接逻辑为以下中一个
1. `cacheKeyPrefix` + 从请求头中`cacheKeyFromHeader`对应字段提取的内容
2. `cacheKeyPrefix` + 从请求体中`cacheKeyFromBody`对应字段提取的内容
**注意**`cacheKeyFromHeader``cacheKeyFromBody` 不能同时配置(非空情况下只支持配置一项)。如果同时配置,插件在配置解析阶段会报错。
命中缓存插件的情况下,返回的响应头中有三种状态:
- `x-cache-status: hit` ,表示命中缓存,直接返回缓存内容
- `x-cache-status: miss` ,表示未命中缓存,返回后端响应结果
- `x-cache-status: skip` ,表示跳过缓存检查
## 配置示例
### 基础配置
```yaml
cache:
type: redis
serviceName: my-redis.dns
servicePort: 6379
timeout: 2000
cacheKeyFromHeader: "x-http-cache-key"
cacheValueFromBodyType: "application/json"
cacheValueFromBody: "messages.@reverse.0.content"
```
假设请求为
```bash
# Request
curl -H "x-http-cache-key: abcd" <url>
# Response
{"messages":[{"content":"1"}, {"content":"2"}, {"content":"3"}]}
```
则缓存的key为`higress-response-cache:abcd`缓存的value为`3`
后续请求命中缓存时响应Content-type返回为 `application/json`
### 响应body作为value
如果缓存所有响应body则可以配置为
```yaml
cacheValueFromBodyType: "text/html"
cacheValueFromBody: ""
```
后续请求命中缓存时响应Content-type返回为 `text/html`
### 请求body作为key
使用请求body作为key则可以配置为
```yaml
cacheKeyFromBody: ""
```
配置支持GJSON PATH语法。
## 进阶用法
Body为`application/json`时,支持基于 GJSON PATH 语法:
比如表达式:`messages.@reverse.0.content` ,含义是把 messages 数组反转后取第一项的 content
GJSON PATH 也支持条件判断语法,例如希望取最后一个 role 为 user 的 content 作为 key可以写成 `messages.@reverse.#(role=="user").content`
如果希望将所有 role 为 user 的 content 拼成一个数组作为 key可以写成`messages.@reverse.#(role=="user")#.content`
还可以支持管道语法,例如希望取到数第二个 role 为 user 的 content 作为 key可以写成`messages.@reverse.#(role=="user")#.content|1`
更多用法可以参考[官方文档](https://github.com/tidwall/gjson/blob/master/SYNTAX.md),可以使用 [GJSON Playground](https://gjson.dev/) 进行语法测试。
## 常见问题
1. 如果返回的错误为 `error status returned by host: bad argument`,请检查:
- `serviceName`是否正确包含了服务的类型后缀(.dns等)
- `servicePort`配置是否正确,尤其是 `static` 类型的服务端口现在固定为 80