配置 gRPC 代理
API7 企业版支持代理 gRPC 流量,让你可以使用与 HTTP 服务相同的流量管理、安全和可观测性能力来管理 gRPC 服务。你 还可以将 RESTful HTTP 请求转码为 gRPC,并为基于浏览器的客户端启用 gRPC-Web 支持。
前提条件
- API7 企业版实例正在运行。
- 已创建网关组,并且网关实例正在运行。
- Dashboard Token。
- 如果你希望直接验证示例 gRPC 服务器并测试原生 gRPC 代理,请安装
grpcurl。
启动示例 gRPC 服务器
启动 API7 企业版 gRPC 最佳实践指南中使用的同一个示例 gRPC 服务器:
docker run -d \
--name grpc-service \
-p 50051:50051 \
api7/grpc-server-example:1.0.0
该服务器暴露 helloworld.Greeter 服务,以及以下示例中使用的 SayHello 方法。
你可以使用 grpcurl 直接验证上游:
grpcurl -plaintext 127.0.0.1:50051 list helloworld.Greeter
以下示例假设网关可以通过 host.docker.internal 访问 Docker 主机。如果你的环境使用其他主机地址,请将 host.docker.internal 替换为该地址。
为原生 gRPC 启用 HTTP/2 监听器
对于原生 gRPC 和 gRPC-Web 验证,网关必须在客户端可访问的监听器上接收 HTTP/2 流量。在基于 Docker 的本地环境中,可以发布一个额外端口,例如 9081,并在该端口上启用 HTTP/2。
如果网关容器已经运行,请使用 -p 9081:9081 重新创建容器,然后更新网关配置:
docker exec <gateway-container-name> /bin/sh -c "cat > /usr/local/apisix/conf/config.yaml <<'EOF'
nginx_config:
error_log_level: warn
apisix:
node_listen:
- port: 9080
enable_http2: true
- port: 9081
enable_http2: true
EOF"
docker exec <gateway-container-name> apisix reload
使用新的 9081 监听器验证原生 gRPC。
基础 gRPC 代理
要代理 gRPC 流量,需要将上游scheme 设置为 grpc 或 grpcs(用于加密 gRPC)。
配置 gRPC 服务和路由
创建一个使用 grpc scheme 的服务,并创建指向该服务的路由。
- Admin API
- ADC
# 1. 创建 gRPC 服务
curl -k "https://localhost:7443/apisix/admin/services/grpc-service?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "grpc-service",
"upstream": {
"type": "roundrobin",
"scheme": "grpc",
"nodes": [
{
"host": "host.docker.internal",
"port": 50051,
"weight": 100
}
]
}
}'
# 2. 为该服务创建路由
curl -k "https://localhost:7443/apisix/admin/routes/grpc-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "grpc-route",
"methods": ["GET", "POST"],
"paths": ["/helloworld.Greeter/SayHello"],
"service_id": "grpc-service"
}'
services:
- name: grpc-service
upstream:
scheme: grpc
type: roundrobin
nodes:
- host: host.docker.internal
port: 50051
weight: 100
routes:
- name: grpc-route
uris:
- /helloworld.Greeter/SayHello
methods:
- GET
- POST
adc sync -f adc.yaml
REST 到 gRPC 转码
grpc-transcode插件允许你将 gRPC 服务暴露为 RESTful API。网关会处理 HTTP/JSON 与 gRPC/Protobuf 之间的转换。
第 1 步:上传 Proto 定义
首先,将你的 .proto 文件内容上传到网关。
- Admin API
- ADC
curl -k "https://localhost:7443/apisix/admin/protos/helloworld-proto?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"id": "helloworld-proto",
"content": "syntax = \"proto3\";\n\npackage helloworld;\n\nservice Greeter {\n rpc SayHello (HelloRequest) returns (HelloReply) {}\n}\n\nmessage HelloRequest {\n string name = 1;\n}\n\nmessage HelloReply {\n string message = 1;\n}"
}'
ADC 当前不支持 protobuf 资源。请先通过 Admin API 上传 protobuf 定义,然后从 ADC 管理的路由中引用已上传的 proto_id。
第 2 步:使用 grpc-transcode 配置路由
创建一个路由,并启用 grpc-transcode插件,同时引用 proto_id、服务名称和方法。
- Admin API
- ADC
curl -k "https://localhost:7443/apisix/admin/routes/grpc-transcode-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "grpc-transcode-route",
"methods": ["POST"],
"paths": ["/hello"],
"service_id": "grpc-service",
"plugins": {
"grpc-transcode": {
"proto_id": "helloworld-proto",
"service": "helloworld.Greeter",
"method": "SayHello"
}
}
}'
services:
- name: grpc-service
upstream:
scheme: grpc
type: roundrobin
nodes:
- host: host.docker.internal
port: 50051
weight: 100
routes:
- name: grpc-transcode-route
uris:
- /hello
methods:
- POST
plugins:
grpc-transcode:
_state: enabled
proto_id: helloworld-proto
service: helloworld.Greeter
method: SayHello
adc sync -f adc.yaml
面向浏览器客户端的 gRPC-Web
grpc-web插件允许基于浏览器的客户端使用 gRPC-Web 协议与 gRPC 服务交互。
- Admin API
- ADC
curl -k "https://localhost:7443/apisix/admin/routes/grpc-web-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "grpc-web-route",
"methods": ["GET", "POST"],
"paths": ["/helloworld.Greeter/SayHello"],
"service_id": "grpc-service",
"plugins": {
"grpc-web": {
"cors_allow_headers": "content-type,x-grpc-web,x-user-agent"
}
}
}'
services:
- name: grpc-service
upstream:
scheme: grpc
type: roundrobin
nodes:
- host: host.docker.internal
port: 50051
weight: 100
routes:
- name: grpc-web-route
uris:
- /helloworld.Greeter/SayHello
methods:
- GET
- POST
plugins:
grpc-web:
_state: enabled
cors_allow_headers: "content-type,x-grpc-web,x-user-agent"
adc sync -f adc.yaml
验证配置
预置示例 gRPC上游并上传匹配的 protobuf 定义后,你可以向已配置的路由发送标准 HTTP POST 请求,以测试 REST 到 gRPC 转码。
curl -X POST http://localhost:9080/hello -d '{"name": "API7"}'
网关会将 JSON 请求体转码为 Protobuf 消息,调用 gRPC 服务,并以 JSON 形式返回响应:
{"message": "Hello API7"}
要验证原生 gRPC 代理,请先在网关上启用面向客户端的 HTTP/2 监听器(例如 9081),然后使用 grpcurl 发送请求:
grpcurl -plaintext \
-proto helloworld.proto \
-d '{"name":"API7"}' \
127.0.0.1:9081 \
helloworld.Greeter.SayHello
后续步骤
- 配置 WebSocket 代理 — 了解如何处理长连接 WebSocket。
- 配置 GraphQL 代理 — 探索 GraphQL 感知的流量管理。