API7 网关 AI Agent Skill:grpc-transcode 插件
概览
grpc-transcode 插件会将 HTTP/JSON 请求转换为 gRPC 调用,并将 gRPC 响应返回为 JSON。客户端发送标准 HTTP 请求,API7 企业版使用预先上传的 protobuf 定义将其转换为 gRPC 请求,转发到 gRPC 上游,再将响应返回为 JSON。gRPC 服务无需修改。
适用场景
- 通过 RESTful HTTP 端点公开 gRPC 服务。
- 允许浏览器或移动客户端在没有 gRPC 客户端库的情况下调用 gRPC 服务。
- 为 gRPC 服务添加 HTTP API 网关功能(身份认证、限流、日志)。
- 逐步从 REST 迁移到 gRPC。
- 将 gRPC 错误详情解码为人类可读的 JSON。
插件配置参考(路由/服务)
| 字段 | 类型 | 是否必填 | 默认 值 | 说明 |
|---|---|---|---|---|
proto_id | string/integer | 是 | — | proto 资源 ID(通过 a7 proto create 上传)。 |
service | string | 是 | — | 完全限定的 gRPC 服务名称(例如 helloworld.Greeter)。 |
method | string | 是 | — | gRPC 方法名称(例如 SayHello)。 |
deadline | number | 否 | 0 | gRPC 调用的截止时间,单位为毫秒。0 表示无截止时间。 |
pb_option | array[string] | 否 | — | Protobuf 序列化选项(见下表)。 |
show_status_in_body | boolean | 否 | false | 出错时将解析后的 grpc-status-details-bin 包含在 JSON 响应体中。 |
status_detail_type | string | 否 | — | gRPC 错误状态中 details 字段的消息类型。解码错误详情时必须设置。 |
pb_option 值
| 选项 | 说明 |
|---|---|
enum_as_name | 将枚举字段返回为字符串名称(例如 "PENDING") |
enum_as_value | 将枚举字段返回为整数值(例如 1) |
int64_as_number | 将 int64 返回为 JSON 数字(JavaScript 中可能丢失精度) |
int64_as_string | 将 int64 返回为字符串(可避免 JavaScript 客户端中的精度丢失) |
int64_as_hexstring | 将 int64 返回为十六进制字符串 |
auto_default_values | 为未设置的字段自动填充默认值 |
no_default_values | 不为未设置的字段添加默认值 |
use_default_values | 使用 proto 定义的默认值 |
多个选项可以组合使用:["int64_as_string", "enum_as_name"]
分步指南:设置 gRPC 转码
1. 上传 proto 定义
将其上传到 default 网关组:
a7 proto create --gateway-group default -f - <<'EOF'
{
"id": "1",
"content": "syntax = \"proto3\";\npackage helloworld;\nservice Greeter {\n rpc SayHello (HelloRequest) returns (HelloReply) {}\n}\nmessage HelloRequest {\n string name = 1;\n}\nmessage HelloReply {\n string message = 1;\n}"
}
EOF
2. 使用 grpc-transcode 创建路由
a7 route create --gateway-group default -f - <<'EOF'
{
"id": "grpc-hello",
"methods": ["GET", "POST"],
"uri": "/grpc/hello",
"plugins": {
"grpc-transcode": {
"proto_id": "1",
"service": "helloworld.Greeter",
"method": "SayHello"
}
},
"upstream": {
"scheme": "grpc",
"type": "roundrobin",
"nodes": [{"host": "grpc-server", "port": 50051, "weight": 1}]
}
}
EOF
**重要:**该上游的 scheme 必须为 "grpc"(使用 TLS 时为 "grpcs")。
3. 测试端点
# 通过查询字符串传递参数
curl "http://localhost:9080/grpc/hello?name=world"
# 响应:{"message":"Hello world"}
# 或通过 POST 请求体传递
curl -X POST http://localhost:9080/grpc/hello \
-H "Content-Type: application/json" \
-d '{"name": "world"}'
常见模式
包含 import 的 Proto(使用已编译的 .pb 文件)
如果 proto 包含 import 语句,请先将其编译为 .pb 文件:
protoc --include_imports --descriptor_set_out=service.pb proto/service.proto
然后将 Base64 编码的 .pb 文件上传到 prod 网关组:
a7 proto create --gateway-group prod -f - <<EOF
{
"id": "2",
"content": "$(base64 -i service.pb)"
}
EOF
为 JavaScript 客户端安全处理 int64
{
"plugins": {
"grpc-transcode": {
"proto_id": "1",
"service": "order.OrderService",
"method": "GetOrder",
"pb_option": ["int64_as_string"]
}
}
}
gRPC 错误详情解码
{
"plugins": {
"grpc-transcode": {
"proto_id": "1",
"service": "helloworld.Greeter",
"method": "SayHello",
"show_status_in_body": true,
"status_detail_type": "helloworld.ErrorDetail"
}
}
}
使用 deadline 控制超时
{
"plugins": {
"grpc-transcode": {
"proto_id": "1",
"service": "slow.SlowService",
"method": "LongRunning",
"deadline": 5000
}
}
}
故障排查
| 现象 | 原因 | 解决方法 |
|---|---|---|
| "can not find proto" | proto ID 不存在 | 使用 a7 proto get <id> 验证 |
| "method not found" | 服务或方法名称不匹配 | 使用完全限定名称:package.Service,并注意大小写 |
| 无法连接上游 | scheme 或端口错误 | 将上游 scheme 设置为 grpc,并确认端口为 gRPC 端口 |
| proto 导入错误 | proto 包含 imports,但上传了原始内容 | 使用 protoc --include_imports 编译为 .pb |
| int64 值损坏 | JavaScript 精度丢失 | 使用 pb_option: ["int64_as_string"] |
| gRPC 调用无提示超时 | 未设置 deadline | 将 deadline 设置为毫秒数 |
| 502 Bad Gateway | gRPC 服务未运行或无法访问 | 检查 gRPC 服务和端口是否可用 |
| 配置未生效 | 指定了错误的网关组 | 确保 --gateway-group 与目标网关组一致 |
配置同步示例
version: "1"
gateway_group: default
protos:
- id: helloworld-proto
content: |
syntax = "proto3";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
routes:
- id: grpc-hello
methods:
- GET
- POST
uri: /grpc/hello
plugins:
grpc-transcode:
proto_id: helloworld-proto
service: helloworld.Greeter
method: SayHello
pb_option:
- int64_as_string
- enum_as_name
upstream:
scheme: grpc
type: roundrobin
nodes:
- host: grpc-server
port: 50051
weight: 1
本页面由 api7/a7 仓库中的 a7-plugin-grpc-transcode/SKILL.md 生成。你可以在 AI Agent Skills 页面查看所有技能。