graphql-proxy-cache
graphql-proxy-cache 插件在内存或磁盘中缓存成功的 GraphQL 查询响应。它支持 GraphQL GET 和 POST 请求,并返回 Apisix-Cache-Status 响应头,用于标识缓存未命中、命中或绕过。
缓存键包含插件配置版本、请求主机、路由 ID、服务 ID、已认证的消费者身份以及完整的 GraphQL 请求数据。消费者隔离默认启用,避免已认证消费者共享缓存响应。GraphQL Mutation 操作会绕过缓存。
对于 GET 请求,请在 query 查询参数中提供 GraphQL 文档。POST 请求可以使用包含 query 字段的 JSON 请求体,也可以使用 application/graphql 请求体。
该插件仅接受 GET 和 POST 请求。其他方法会返回 HTTP 405;无法读取、格式错误或无效的 GraphQL 请求会返回 HTTP 400。
示例
以下示例使用公开的 Countries GraphQL API,并始终使用同一查询:
query {
country(code: "US") {
name
capital
}
}
在磁盘中缓存响应
默认策略把缓存响应存储在配置的磁盘缓存路径下。如果缓存数据需要在容器替换后保留,请将该路径持久化到临时容器之外。
创建一个具有稳定 ID 的路由,以便缓存清除示例使用相同的值:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes/graphql-proxy-cache-route" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"uri": "/graphql",
"plugins": {
"graphql-proxy-cache": {}
},
"upstream": {
"type": "roundrobin",
"pass_host": "node",
"scheme": "https",
"nodes": {
"countries.trevorblades.com:443": 1
}
}
}'
services:
- name: graphql-proxy-cache
labels:
docs-example: graphql-proxy-cache
routes:
- id: graphql-proxy-cache-route
name: graphql-proxy-cache
uris:
- /graphql
plugins:
graphql-proxy-cache: {}
upstream:
type: roundrobin
scheme: https
pass_host: node
nodes:
- host: countries.trevorblades.com
port: 443
weight: 1
预览此示例所管理的变更,并确认差异中没有非预期的更新或删除:
adc diff -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=graphql-proxy-cache
同步已检查的服务配置:
adc sync -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=graphql-proxy-cache
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: countries-graphql
spec:
type: ExternalName
externalName: countries.trevorblades.com
ports:
- name: https
port: 443
targetPort: 443
---
apiVersion: apisix.apache.org/v1alpha1
kind: BackendTrafficPolicy
metadata:
namespace: aic
name: countries-graphql-https
spec:
targetRefs:
- name: countries-graphql
kind: Service
group: ""
sectionName: https
passHost: node
scheme: https
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: graphql-proxy-cache
spec:
plugins:
- name: graphql-proxy-cache
config: {}
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: graphql-proxy-cache
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /graphql
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: graphql-proxy-cache
backendRefs:
- name: countries-graphql
port: 443
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: countries-graphql
spec:
ingressClassName: apisix
scheme: https
passHost: node
externalNodes:
- type: Domain
name: countries.trevorblades.com
port: 443
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: graphql-proxy-cache
spec:
ingressClassName: apisix
http:
- name: graphql-proxy-cache
match:
paths:
- /graphql
upstreams:
- name: countries-graphql
plugins:
- name: graphql-proxy-cache
enable: true
config: {}
应用配置:
kubectl apply -f graphql-proxy-cache-ic.yaml
发送查询并检查缓存响应头:
curl -i "http://127.0.0.1:9080/graphql" -X POST \
-H "Content-Type: application/json" \
-d '{"query":"query { country(code: \"US\") { name capital } }"}'
第一次请求应返回 Apisix-Cache-Status: MISS。重复发送相同请求应返回 Apisix-Cache-Status: HIT。响应体应包含:
{
"data": {
"country": {
"capital": "Washington D.C.",
"name": "United States"
}
}
}
Countries API 会发送自己的长期有效 Cache-Control 响应头。使用磁盘缓存时,该上游响应头的优先级高于网关的后备 apisix.proxy_cache.cache_ttl 值。
清除磁盘缓存条目
通过受 key-auth 保护的路由公开插件的缓存清除端点:
- Admin API
- ADC
- Ingress Controller
创建缓存运维消费者:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "cache-operator"
}'
为消费者添加 key-auth 凭据:
curl "http://127.0.0.1:9180/apisix/admin/consumers/cache-operator/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cache-operator-key-auth",
"plugins": {
"key-auth": {
"key": "purge-key"
}
}
}'
创建受保护的缓存清除路由:
curl "http://127.0.0.1:9180/apisix/admin/routes/graphql-cache-purge" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"uri": "/apisix/plugin/graphql-proxy-cache/*",
"plugins": {
"key-auth": {},
"public-api": {}
}
}'
consumers:
- username: cache-operator
labels:
docs-example: graphql-cache-purge
credentials:
- name: cache-operator-key-auth
type: key-auth
config:
key: purge-key
services:
- name: graphql-cache-purge
labels:
docs-example: graphql-cache-purge
routes:
- id: graphql-cache-purge
name: graphql-cache-purge
uris:
- /apisix/plugin/graphql-proxy-cache/*
plugins:
key-auth: {}
public-api: {}
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
该服务的上游用于满足 ADC 服务 Schema。public-api 插件在网关内部处理缓存清除请求,因此这些请求不会被代理到该上游。
预览此示例所管理的变更,并确认差异中没有非预期的更新或删除:
adc diff -f purge-adc.yaml \
--include-resource-type service \
--include-resource-type consumer \
--label-selector docs-example=graphql-cache-purge
同步已检查的服务和消费者配置:
adc sync -f purge-adc.yaml \
--include-resource-type service \
--include-resource-type consumer \
--label-selector docs-example=graphql-cache-purge
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: cache-operator
spec:
gatewayRef:
name: apisix
credentials:
- type: key-auth
name: cache-operator-key-auth
config:
key: purge-key
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: graphql-cache-purge
spec:
plugins:
- name: key-auth
config: {}
- name: public-api
config: {}
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: graphql-cache-purge
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: PathPrefix
value: /apisix/plugin/graphql-proxy-cache/
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: graphql-cache-purge
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: cache-operator
spec:
ingressClassName: apisix
authParameter:
keyAuth:
value:
key: purge-key
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: graphql-cache-purge
spec:
ingressClassName: apisix
http:
- name: graphql-cache-purge
match:
paths:
- /apisix/plugin/graphql-proxy-cache/*
plugins:
- name: key-auth
enable: true
- name: public-api
enable: true
应用配置:
kubectl apply -f graphql-cache-purge-ic.yaml
发送磁盘缓存请求并保存生成的缓存键:
export CACHE_KEY="$(
curl -sS -D - -o /dev/null "http://127.0.0.1:9080/graphql" -X POST \
-H "Content-Type: application/json" \
-d '{"query":"query { country(code: \"US\") { name capital } }"}' | \
awk 'tolower($1) == "apisix-cache-key:" {gsub("\\r", "", $2); print $2}'
)"
Admin API 和 ADC 工作流使用稳定的路由 ID graphql-proxy-cache-route:
export CACHE_ROUTE_ID=graphql-proxy-cache-route
对于 Ingress Controller 部署,请根据使用的资源设置生成的路由名称:
- Gateway API
- APISIX CRD
export CACHE_ROUTE_NAME=aic_graphql-proxy-cache_0-0
export CACHE_ROUTE_NAME=aic_graphql-proxy-cache_graphql-proxy-cache
通过 Admin API 获取对应的网关路由 ID:
export CACHE_ROUTE_ID="$(
curl -fsS "http://127.0.0.1:9180/apisix/admin/routes" \
-H "X-API-KEY: ${ADMIN_API_KEY}" | \
jq -er --arg name "$CACHE_ROUTE_NAME" '
.list[].value
| select(.name == $name)
| .id
'
)"
清除缓存响应:
curl -i "http://127.0.0.1:9080/apisix/plugin/graphql-proxy-cache/disk/${CACHE_ROUTE_ID}/${CACHE_KEY}" \
-X PURGE \
-H "apikey: purge-key"
第一次清除请求应返回 200 OK。重复发送该请求应返回 404 Not Found,确认磁盘条目已不存在。
包含 Vary 响应头的响应可能生成多个缓存变体。磁盘缓存清除成功会移除目标条目,但不能保证所有变体均已移除。
在内存中缓存响应
更新现有缓存路由以使用内存缓存。应用此示例之前,请先在静态配置中定义缓存区域。
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes/graphql-proxy-cache-route" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"uri": "/graphql",
"plugins": {
"graphql-proxy-cache": {
"cache_strategy": "memory",
"cache_zone": "memory_cache",
"cache_ttl": 10
}
},
"upstream": {
"type": "roundrobin",
"pass_host": "node",
"scheme": "https",
"nodes": {
"countries.trevorblades.com:443": 1
}
}
}'
services:
- name: graphql-proxy-cache
labels:
docs-example: graphql-proxy-cache
routes:
- id: graphql-proxy-cache-route
name: graphql-proxy-cache
uris:
- /graphql
plugins:
graphql-proxy-cache:
cache_strategy: memory
cache_zone: memory_cache
cache_ttl: 10
upstream:
type: roundrobin
scheme: https
pass_host: node
nodes:
- host: countries.trevorblades.com
port: 443
weight: 1
预览更新:
adc diff -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=graphql-proxy-cache
同步已检查的服务配置:
adc sync -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=graphql-proxy-cache
- Gateway API
- APISIX CRD
更新现有插件配置:
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: graphql-proxy-cache
spec:
plugins:
- name: graphql-proxy-cache
config:
cache_strategy: memory
cache_zone: memory_cache
cache_ttl: 10
更新现有路由:
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: graphql-proxy-cache
spec:
ingressClassName: apisix
http:
- name: graphql-proxy-cache
match:
paths:
- /graphql
upstreams:
- name: countries-graphql
plugins:
- name: graphql-proxy-cache
enable: true
config:
cache_strategy: memory
cache_zone: memory_cache
cache_ttl: 10
应用完整的更新后资源:
kubectl apply -f graphql-proxy-cache-ic.yaml
❶ cache_strategy:设置为 memory,将响应存储在内存中。
❷ cache_zone:设置为已配置的内存缓存区域名称。
❸ cache_ttl:设置内存缓存的生存时间,单位为秒。
连续发送两次 GraphQL 请求。第一次响应应报告 MISS,第二次应报告 HIT。等待至少十秒后再次发送;由于内存条目已过期,响应应再次报告 MISS。