graphql-proxy-cache
graphql-proxy-cache 插件使用磁盘或内存缓存 GraphQL 查询响应。它支持 GraphQL GET 和 POST 请求。
该插件根据插件配置版本、请求主机、路由 ID、服务 ID、已认证的消费者身份以及完整的 GraphQL 请求体生成 MD5 缓存键。当 APISIX 将请求解析为消费者或远程用户时,默认会将消费者身份包含在缓存键中。
如果请求包含 变更(Mutation) 操作,插件将不会缓存数据。相反,它会在响应中添加 Apisix-Cache-Status: BYPASS 头,以表明该请求绕过了缓存机制。
示例
以下示例使用公开的 Countries GraphQL API 作为上游,并演示了如何在不同场景下配置 graphql-proxy-cache。
在磁盘上缓存数据
与内存缓存相比,磁盘缓存策略具有系统重启时数据持久化和存储容量更大的优点。它适用于优先考虑持久性并且可以容忍稍大的缓存访问延迟的应用程序。
以下示例演示了如何在路由上使用 graphql-proxy-cache 插件将数据缓存到磁盘上。
创建一个启用了 graphql-proxy-cache 插件的路由,使用默认配置将数据缓存到磁盘:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "graphql-proxy-cache-route",
"uri": "/graphql",
"plugins": {
"graphql-proxy-cache": {}
},
"upstream": {
"type": "roundrobin",
"pass_host": "node",
"scheme": "https",
"nodes": {
"countries.trevorblades.com:443": 1
}
}
}'
services:
- name: graphql-service
routes:
- uris:
- /graphql
name: graphql-proxy-cache-route
plugins:
graphql-proxy-cache: {}
upstream:
type: roundrobin
scheme: https
nodes:
- host: countries.trevorblades.com
port: 443
weight: 1
将配置同步到网关:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: countries-graphql-external-domain
spec:
type: ExternalName
externalName: countries.trevorblades.com
---
apiVersion: apisix.apache.org/v1alpha1
kind: BackendTrafficPolicy
metadata:
namespace: aic
name: countries-graphql-https
spec:
targetRefs:
- name: countries-graphql-external-domain
kind: Service
group: ""
passHost: node
scheme: https
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: graphql-proxy-cache-plugin-config
spec:
plugins:
- name: graphql-proxy-cache
config:
_meta:
disable: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: graphql-proxy-cache-route
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-plugin-config
backendRefs:
- name: countries-graphql-external-domain
port: 443
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: countries-graphql-external-domain
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-route
spec:
ingressClassName: apisix
http:
- name: graphql-proxy-cache-route
match:
paths:
- /graphql
upstreams:
- name: countries-graphql-external-domain
plugins:
- name: graphql-proxy-cache
enable: true
将配置应用到集群:
kubectl apply -f graphql-proxy-cache-ic.yaml
发送一个带有 GraphQL 查询的请求进行验证:
curl -i "http://127.0.0.1:9080/graphql" -X POST \
-H "Content-Type: application/json" \
-d '{"query": "query { country(code: \"US\") { name capital } }"}'
你应该会看到一个 HTTP/1.1 200 OK 响应,其中包含以下响应头,表明插件已成功启用:
APISIX-Cache-Key: 5908e74856ea02835af198678b879a71
Apisix-Cache-Status: MISS
由于第一个响应之前没有可用缓存,因此显示 Apisix-Cache-Status: MISS。确切的缓存键取决于你的配置。
在缓存 TTL 窗口内再次发送相同的请求。你应该会看到 HTTP/1.1 200 OK 响应,并带有以下响应头,表明缓存命中:
APISIX-Cache-Key: 5908e74856ea02835af198678b879a71
Apisix-Cache-Status: HIT
等待缓存超过 TTL 后过期,然后再次发送相同的请求。你应该会看到 HTTP/1.1 200 OK 响应,并带有以下响应头,表明缓存已过期:
APISIX-Cache-Key: 5908e74856ea02835af198678b879a71
Apisix-Cache-Status: EXPIRED
在内存中缓存数据
内存缓存策略具有访问缓存数据延迟低的优点,因为从 RAM 检索数据比从磁盘存储检索数据更快。它也适用于存储不需要长期持久化的临时数据,从而可以高效地缓存经常更改的数据。
以下示例演示了如何在路由上使用 graphql-proxy-cache 插件将数据缓存到内存中。
创建一个启用了 graphql-proxy-cache 的路由,并将其配置为使用基于内存的缓存:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "graphql-proxy-cache-route",
"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-service
routes:
- uris:
- /graphql
name: graphql-proxy-cache-route
plugins:
graphql-proxy-cache:
cache_strategy: memory
cache_zone: memory_cache
cache_ttl: 10
upstream:
type: roundrobin
scheme: https
nodes:
- host: countries.trevorblades.com
port: 443
weight: 1
将配置同步到网关:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: countries-graphql-external-domain
spec:
type: ExternalName
externalName: countries.trevorblades.com
---
apiVersion: apisix.apache.org/v1alpha1
kind: BackendTrafficPolicy
metadata:
namespace: aic
name: countries-graphql-https
spec:
targetRefs:
- name: countries-graphql-external-domain
kind: Service
group: ""
passHost: node
scheme: https
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: graphql-proxy-cache-plugin-config
spec:
plugins:
- name: graphql-proxy-cache
config:
cache_strategy: memory
cache_zone: memory_cache
cache_ttl: 10
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: graphql-proxy-cache-route
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-plugin-config
backendRefs:
- name: countries-graphql-external-domain
port: 443
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: countries-graphql-external-domain
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-route
spec:
ingressClassName: apisix
http:
- name: graphql-proxy-cache-route
match:
paths:
- /graphql
upstreams:
- name: countries-graphql-external-domain
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 查询的请求进行验证:
curl "http://127.0.0.1:9080/graphql" -i -X POST \
-H "Content-Type: application/json" \
-d '{"query": "query { country(code: \"US\") { name capital } }"}'
你应该会看到一个 HTTP/1.1 200 OK 响应,其中包含以下响应头,表明插件已成功启用:
APISIX-Cache-Key: a661316c4b1b70ae2db5347743dec6b6
Apisix-Cache-Status: MISS
由于第一个响应之前没有可用缓存,因此显示 Apisix-Cache-Status: MISS。确切的缓存键取决于你的配置。
在缓存 TTL 窗口内再次发送相同的请求。你应该会看到 HTTP/1.1 200 OK 响应,并带有以下响应头,表明缓存命中:
APISIX-Cache-Key: a661316c4b1b70ae2db5347743dec6b6
Apisix-Cache-Status: HIT
手动清除缓存
虽然大多数时候不需要这样做,但在某些情况下,你可能希望手动清除缓存数据。
以下示例演示了如何使用 public-api 插件公开由 graphql-proxy-cache 插件创建的 /apisix/plugin/graphql-proxy-cache/{cache_strategy}/{route_id}/{key} 端点。该示例还启用了 key-auth,确保只有通过身份认证的运维人员才能清除缓存响应。
创建一个带有 key-auth 凭证的消费者,以及一个匹配 URI /apisix/plugin/graphql-proxy-cache/* 的路由:
- 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"
}'
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" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "graphql-cache-purge",
"uri": "/apisix/plugin/graphql-proxy-cache/*",
"plugins": {
"key-auth": {},
"public-api": {}
}
}'
consumers:
- username: cache-operator
credentials:
- name: cache-operator-key-auth
type: key-auth
config:
key: purge-key
services:
- name: graphql-cache-purge-service
routes:
- name: graphql-cache-purge-route
uris:
- /apisix/plugin/graphql-proxy-cache/*
plugins:
key-auth: {}
public-api: {}
将配置同步到网关:
adc sync -f adc.yaml
- 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-plugin-config
spec:
plugins:
- name: key-auth
config:
_meta:
disable: false
- name: public-api
config:
_meta:
disable: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: graphql-cache-purge-route
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-plugin-config
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-route
spec:
ingressClassName: apisix
http:
- name: graphql-cache-purge-route
match:
paths:
- /apisix/plugin/graphql-proxy-cache/*
plugins:
- name: key-auth
enable: true
- name: public-api
enable: true
将配置应用到集群:
kubectl apply -f graphql-proxy-cache-ic.yaml
发送磁盘缓存请求,并保存生成的 APISIX-Cache-Key 响应头:
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}')
使用该值和包含 graphql-proxy-cache 的路由 ID 发送 PURGE 请求:
curl -i "http://127.0.0.1:9080/apisix/plugin/graphql-proxy-cache/disk/graphql-proxy-cache-route/${CACHE_KEY}" -X PURGE \
-H "apikey: purge-key"
Admin API 和 ADC 示例使用 graphql-proxy-cache-route 作为路由 ID。对于 Ingress Controller 部署,请将其替换为生成的 APISIX 路由 ID。
HTTP/1.1 200 OK 响应验证了与该键对应的缓存已成功清除。
如果你再次发送相同的 PURGE 请求,应该会看到 HTTP/1.1 404 Not Found 响应,表明清除缓存后,磁盘上不再存在使用该缓存键的缓存。
包含 Vary 响应头的响应可能会产生多个缓存变体。PURGE 请求成功仅表示目标缓存条目已清除,并不能保证所有变体都已清除。