跳到主要内容
版本:3.10.x

API7 网关 AI Agent Skill:GraphQL 代理方案

概览

API7 企业版可以使用解析后的请求体中的 GraphQL 变量 来路由并保护 GraphQL 流量:

  • graphql_name:操作名称,例如 getUser
  • graphql_operation:操作类型,例如 querymutation
  • graphql_root_fields:该操作请求的顶层字段。

使用当前版本的 a7 服务关联路由模型:

  1. 为 GraphQL 后端创建服务。
  2. 使用 pathsservice_id 创建路由。
  3. 通过 a7 route create/update -f 请求体添加 GraphQL vars 和插件。

适用场景

  • 将只读 GraphQL 查询和变更操作路由到不同后端。
  • 对高成本操作应用更严格的限制。
  • 使用 degraphql 暴露会被转换为 GraphQL 的 REST 风格路径。
  • 使用认证和访问控制插件保护敏感 GraphQL 操作。

方案 A:基于操作的路由

为读写 GraphQL 流量分别创建服务。

a7 service create -g prod-group -f - <<'EOF'
{
"id": "gql-read-service",
"name": "gql-read-service",
"upstream": {
"type": "roundrobin",
"nodes": [
{"host": "gql-read-replica", "port": 4000, "weight": 1}
]
}
}
EOF

a7 service create -g prod-group -f - <<'EOF'
{
"id": "gql-write-service",
"name": "gql-write-service",
"upstream": {
"type": "roundrobin",
"nodes": [
{"host": "gql-primary-db", "port": 4000, "weight": 1}
]
}
}
EOF

将 GraphQL 查询(query)路由到读取服务:

a7 route create -g prod-group -f - <<'EOF'
{
"id": "gql-queries",
"name": "gql-queries",
"paths": ["/graphql"],
"service_id": "gql-read-service",
"vars": [["graphql_operation", "==", "query"]]
}
EOF

将 GraphQL mutation 路由到写入服务:

a7 route create -g prod-group -f - <<'EOF'
{
"id": "gql-mutations",
"name": "gql-mutations",
"paths": ["/graphql"],
"service_id": "gql-write-service",
"vars": [["graphql_operation", "==", "mutation"]]
}
EOF

如果通用 /graphql 路由与更具体的 GraphQL 操作路由重叠,请使用路由优先级。

方案 B:按操作限流

对 mutation 流量应用更严格的限制。在更新请求体中包含 service_id,确保路由仍绑定到预期服务。

a7 route update gql-mutations -g prod-group -f - <<'EOF'
{
"service_id": "gql-write-service",
"plugins": {
"key-auth": {},
"limit-count": {
"count": 50,
"time_window": 60,
"key_type": "var",
"key": "consumer_name",
"rejected_code": 429,
"rejected_msg": "Mutation quota exceeded"
}
}
}
EOF

请分别创建消费者和凭证:

a7 consumer create -g prod-group --username frontend-app
a7 credential create -g prod-group --consumer frontend-app --plugins-json '{"key-auth":{"key":"frontend-secret"}}'

方法 C:使用 degraphql 实现 REST 到 GraphQL 转换

degraphql 插件会将 REST 风格路径映射到后端的 GraphQL 查询。

a7 service create -g prod-group -f - <<'EOF'
{
"id": "graphql-engine-service",
"name": "graphql-engine-service",
"upstream": {
"type": "roundrobin",
"nodes": [
{"host": "graphql-engine", "port": 8080, "weight": 1}
]
}
}
EOF

a7 route create -g prod-group -f - <<'EOF'
{
"id": "rest-bridge-user",
"name": "rest-bridge-user",
"paths": ["/api/users/:id"],
"methods": ["GET"],
"service_id": "graphql-engine-service",
"plugins": {
"degraphql": {
"query": "query getUser($id: ID!) { user(id: $id) { name email profile { bio } } }",
"variables": ["id"]
}
}
}
EOF

方法 D:限制 mutation

使用 consumer-restriction 将 mutation 路由限制为仅允许指定消费者或 消费者组访问。

a7 route update gql-mutations -g prod-group -f - <<'EOF'
{
"service_id": "gql-write-service",
"plugins": {
"key-auth": {},
"consumer-restriction": {
"type": "consumer_name",
"whitelist": ["admin-client", "system-client"],
"rejected_code": 403,
"rejected_msg": "Only approved clients can perform mutations"
}
}
}
EOF

声明式管理说明

a7 config sync 可以管理服务和普通的基于服务的路由。GraphQL 操作匹配当前需要 vars 等原始路由请求体字段, 因此请对这些操作特定路由使用 a7 route create/update -f

version: "1"
services:
- id: graphql-engine-service
name: graphql-engine-service
upstream:
type: roundrobin
nodes:
- host: graphql-engine
port: 8080
weight: 1
routes:
- id: rest-bridge-user
name: rest-bridge-user
paths:
- /api/users/:id
methods:
- GET
service_id: graphql-engine-service
plugins:
degraphql:
query: "query getUser($id: ID!) { user(id: $id) { name email profile { bio } } }"
variables:
- id

将其应用到一个网关组:

a7 config sync -g prod-group -f graphql-rest-bridge.yaml

验证

a7 service get gql-read-service -g prod-group -o json
a7 route get gql-queries -g prod-group -o json
a7 route get gql-mutations -g prod-group -o json

流量验证需要已部署的网关和 GraphQL 后端:

curl -X POST https://gateway.prod.example.com/graphql \
-H "Content-Type: application/json" \
-H "apikey: frontend-secret" \
-d '{"query": "query getUser { user(id: 1) { name } }"}'

curl -X POST https://gateway.prod.example.com/graphql \
-H "Content-Type: application/json" \
-H "apikey: frontend-secret" \
-d '{"query": "mutation deleteUser { deleteUser(id: 1) { success } }"}'

重要注意事项

  • 需要解析请求体,才能使用 GraphQL 变量。
  • 批量请求可能只会暴露第一个操作的变量。
  • 多个路由共享 /graphql 时,请使用路由优先级。
  • 将认证凭证保存在 a7 credential 中,不要直接嵌入消费者。

本页面由 api7/a7 仓库中的 a7-recipe-graphql-proxy/SKILL.md 生成。你可以在 AI Agent Skills 页面查看所有技能。