gRPC 调试工具
本章介绍 gRPC 开发中常用的调试和测试工具,包括 grpcurl、grpcui、ghz 等,帮助你更高效地开发和调试 gRPC 服务。
gRPC 反射机制
在介绍工具之前,需要了解 gRPC 的反射机制。反射允许客户端在运行时发现服务的定义,包括方法名称、请求和响应类型。大多数 gRPC 工具都依赖反射来工作。
启用服务端反射
Go 服务端:
import (
"google.golang.org/grpc/reflection"
)
func main() {
s := grpc.NewServer()
// 注册业务服务
pb.RegisterGreeterServer(s, &server{})
// 启用反射
reflection.Register(s)
s.Serve(lis)
}
Python 服务端:
from grpc_reflection.v1alpha import reflection
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
# 注册业务服务
demo_pb2_grpc.add_GreeterServicer_to_server(GreeterServicer(), server)
# 启用反射
SERVICE_NAMES = (
demo_pb2.DESCRIPTOR.services_by_name['Greeter'].full_name,
reflection.SERVICE_NAME,
)
reflection.enable_server_reflection(SERVICE_NAMES, server)
server.add_insecure_port('[::]:50051')
server.start()
server.wait_for_termination()
# 需要安装: pip install grpcio-reflection
Java 服务端:
import io.grpc.protobuf.services.ProtoReflectionService;
public class Server {
public static void main(String[] args) {
Server server = ServerBuilder.forPort(50051)
.addService(new GreeterImpl())
.addService(ProtoReflectionService.newInstance()) // 启用反射
.build()
.start();
}
}
grpcurl
grpcurl 是一个命令行工具,类似于 curl,但专门用于 gRPC 服务。它可以通过反射发现服务,让你轻松调用 gRPC 方法。
安装
macOS:
brew install grpcurl
Linux:
# 下载二进制文件
curl -sSL "https://github.com/fullstorydev/grpcurl/releases/download/v1.8.9/grpcurl_1.8.9_linux_x86_64.tar.gz" | tar -xz -C /usr/local/bin
# 或使用 Go 安装
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
Windows:
# 使用 Chocolatey
choco install grpcurl
# 或使用 Scoop
scoop install grpcurl
基本使用
列出服务
# 列出服务器上的所有服务(需要反射)
grpcurl -plaintext localhost:50051 list
# 输出示例:
# grpc.reflection.v1alpha.ServerReflection
# helloworld.Greeter
查看服务描述
# 查看服务的详细描述
grpcurl -plaintext localhost:50051 describe helloworld.Greeter
# 输出示例:
# helloworld.Greeter is a service:
# service Greeter {
# rpc SayHello ( .helloworld.HelloRequest ) returns ( .helloworld.HelloReply );
# }
查看消息类型
# 查看消息类型的定义
grpcurl -plaintext localhost:50051 describe helloworld.HelloRequest
# 输出示例:
# helloworld.HelloRequest is a message:
# message HelloRequest {
# string name = 1;
# }
调用服务
# 调用一元 RPC
grpcurl -plaintext -d '{"name": "World"}' localhost:50051 helloworld.Greeter/SayHello
# 输出:
# {
# "message": "Hello World"
# }
调用流式 RPC
# 服务端流(客户端发送一个请求)
grpcurl -plaintext -d '{"name": "World"}' localhost:50051 helloworld.Greeter/StreamGreetings
# 客户端流(从文件读取多个请求)
grpcurl -plaintext -d @ localhost:50051 helloworld.Greeter/SendGreetings < requests.json
# requests.json 格式:
# {"name": "Alice"}
# {"name": "Bob"}
# {"name": "Charlie"}
高级选项
使用 TLS
# 使用服务器证书验证
grpcurl -cacert ca.crt localhost:50051 list
# 使用客户端证书(mTLS)
grpcurl -cacert ca.crt -cert client.crt -key client.key localhost:50051 list
# 跳过证书验证(不安全,仅用于测试)
grpcurl -insecure localhost:50051 list
设置超时
# 设置连接超时
grpcurl -plaintext -connect-timeout 5s localhost:50051 list
# 设置最大时间
grpcurl -plaintext -max-time 30s localhost:50051 helloworld.Greeter/SayHello
发送元数据
# 添加请求头
grpcurl -plaintext -H "authorization: Bearer token123" \
-H "request-id: req-001" \
localhost:50051 helloworld.Greeter/SayHello
# 使用 -H 选项添加自定义元数据
grpcurl -plaintext -H "x-custom-header: value" \
localhost:50051 helloworld.Greeter/SayHello
使用 Proto 文件(无反射)
如果服务器没有启用反射,可以手动指定 proto 文件:
# 指定 proto 文件路径
grpcurl -plaintext -proto path/to/helloworld.proto \
-import-path path/to \
localhost:50051 list
# 指定多个导入路径
grpcurl -plaintext \
-proto api.proto \
-import-path ./protos \
-import-path ./vendor \
localhost:50051 list
格式化输出
# 格式化 JSON 输出
grpcurl -plaintext -emit-defaults localhost:50051 helloworld.Greeter/SayHello
# 输出原始格式
grpcurl -plaintext -format text localhost:50051 helloworld.Greeter/SayHello
实用脚本示例
#!/bin/bash
# gRPC 服务健康检查脚本
SERVER="localhost:50051"
SERVICE="helloworld.Greeter"
# 检查服务是否可用
if grpcurl -plaintext -connect-timeout 2s $SERVER list &>/dev/null; then
echo "服务可用: $SERVER"
# 检查特定服务
if grpcurl -plaintext $SERVER list | grep -q "$SERVICE"; then
echo "服务已注册: $SERVICE"
# 调用健康检查
grpcurl -plaintext -d '{"name": "health-check"}' \
$SERVER $SERVICE/SayHello
else
echo "错误: 服务未注册"
fi
else
echo "错误: 无法连接到服务器"
fi
grpcui
grpcui 是一个交互式的 Web 界面,用于调试 gRPC 服务。它基于 grpcurl,提供了更直观的图形界面。
安装
# macOS
brew install grpcui
# Linux/Windows 使用 Go 安装
go install github.com/fullstorydev/grpcui/cmd/grpcui@latest
基本使用
# 启动 Web UI
grpcui -plaintext localhost:50051
# 输出:
# gRPC Web UI available at http://127.0.0.1:51991
启动后,浏览器会自动打开一个 Web 界面,你可以:
- 浏览所有服务和方法
- 查看消息类型定义
- 填写请求参数
- 执行调用并查看响应
常用选项
# 指定绑定端口
grpcui -plaintext -port 8080 localhost:50051
# 绑定到特定地址
grpcui -plaintext -bind 0.0.0.0 localhost:50051
# 使用 TLS
grpcui -insecure localhost:50051
# 添加默认请求头
grpcui -plaintext -H "authorization: Bearer token" localhost:50051
# 使用 proto 文件(无反射)
grpcui -plaintext -proto api.proto localhost:50051
功能特点
- 服务浏览器:树形结构显示所有服务和方法
- 请求编辑器:表单式输入,支持 JSON 编辑
- 历史记录:保存之前的请求
- 响应查看:格式化显示 JSON 响应
- 元数据支持:添加和查看请求/响应元数据
ghz
ghz 是一个 gRPC 基准测试工具,用于测试服务的性能和吞吐量。
安装
# macOS
brew install ghz
# Linux
curl -sSL "https://github.com/bojand/ghz/releases/download/v0.118.0/ghz_0.118.0_Linux_x86_64.tar.gz" | tar -xz -C /usr/local/bin
# Windows
choco install ghz
# 或使用 Go 安装
go install github.com/bojand/ghz/cmd/ghz@latest
基本使用
# 简单的压力测试
ghz --insecure \
--proto ./proto/helloworld.proto \
--call helloworld.Greeter.SayHello \
-d '{"name": "World"}' \
-n 1000 \
-c 10 \
localhost:50051
# 参数说明:
# --insecure : 不使用 TLS
# --proto : proto 文件路径
# --call : 完整的方法名(包名.服务名.方法名)
# -d : 请求数据(JSON 格式)
# -n : 总请求数
# -c : 并发数
输出解读
# 示例输出:
#
# Summary:
# Count: 1000
# Total: 1.23 s
# Slowest: 45.32 ms
# Fastest: 1.24 ms
# Average: 12.30 ms
# Requests/sec: 813.01
#
# Latency distribution:
# 10% in 3.21 ms
# 25% in 5.43 ms
# 50% in 10.12 ms
# 75% in 15.67 ms
# 90% in 25.43 ms
# 95% in 32.11 ms
# 99% in 41.23 ms
#
# Status code distribution:
# [OK] 1000 responses
高级选项
# 使用配置文件
ghz --config benchmark.yaml
# benchmark.yaml 内容:
# proto: "./proto/helloworld.proto"
# call: "helloworld.Greeter.SayHello"
# host: "localhost:50051"
# insecure: true
# total: 10000
# concurrency: 50
# data:
# name: "World"
# rps: 1000 # 每秒请求数限制
# timeout: 10s
# 从文件读取请求数据
ghz --insecure \
--proto ./proto/helloworld.proto \
--call helloworld.Greeter.SayHello \
-D ./requests.json \
-n 1000 \
localhost:50051
# 输出详细报告
ghz --insecure \
--proto ./proto/helloworld.proto \
--call helloworld.Greeter.SayHello \
-d '{"name": "World"}' \
-n 1000 \
-c 10 \
--output result.json \
--format json \
localhost:50051
性能测试策略
# 逐步增加负载测试
for c in 10 50 100 200 500; do
echo "测试并发: $c"
ghz --insecure \
--proto ./proto/helloworld.proto \
--call helloworld.Greeter.SayHello \
-d '{"name": "World"}' \
-n 10000 \
-c $c \
localhost:50051
echo "---"
done
# 持续压力测试(指定持续时间)
ghz --insecure \
--proto ./proto/helloworld.proto \
--call helloworld.Greeter.SayHello \
-d '{"name": "World"}' \
-z 60s \
-c 100 \
localhost:50051
grpcui vs grpcurl 对比
| 特性 | grpcurl | grpcui |
|---|---|---|
| 界面 | 命令行 | Web 界面 |
| 适用场景 | 脚本、自动化测试 | 手动调试、探索 |
| 学习曲线 | 需要熟悉命令 | 直观易用 |
| 历史记录 | 需要手动保存 | 自动保存 |
| 响应格式 | JSON 文本 | 格式化显示 |
| 流式支持 | 支持 | 支持 |
其他实用工具
grpc-health-probe
Kubernetes 健康检查工具:
# 安装
go install github.com/grpc-ecosystem/grpc-health-probe@latest
# 使用
grpc-health-probe -addr=localhost:50051
# 输出:
# status: SERVING
# 检查特定服务
grpc-health-probe -addr=localhost:50051 -service=helloworld.Greeter
# 在 Kubernetes 中使用
# livenessProbe:
# exec:
# command: ["/bin/grpc_health_probe", "-addr=:50051"]
# initialDelaySeconds: 5
# periodSeconds: 10
grpc_cli
gRPC 官方命令行工具:
# 注意:grpc_cli 已不再积极维护,建议使用 grpcurl
# 安装(需要编译)
git clone https://github.com/grpc/grpc
cd grpc
make grpc_cli
# 使用
./grpc_cli ls localhost:50051
./grpc_cli call localhost:50051 helloworld.Greeter.SayHello "name: 'World'"
Postman
Postman 从 v10.14 版本开始支持 gRPC:
- 创建新的 gRPC 请求
- 输入服务器地址
- 加载 proto 文件或使用反射
- 选择方法并发送请求
Postman 的优势:
- 图形界面友好
- 支持环境变量
- 支持集合和测试脚本
- 支持团队协作
BloomRPC(已停止维护)
BloomRPC 是一个流行的 gRPC GUI 客户端,但已停止维护。推荐使用:
- grpcui(命令行启动的 Web UI)
- Postman(支持 gRPC)
- Kreya(专门为 gRPC 设计的 GUI 客户端)
最佳实践
1. 开发环境工具链
# 开发时推荐配置
# 1. 启用服务端反射(仅在开发环境)
# 2. 使用 grpcui 进行手动测试
# 3. 使用 grpcurl 编写自动化测试脚本
# 4. 使用 ghz 进行性能测试
2. CI/CD 集成
# GitLab CI 示例
grpc-test:
stage: test
script:
# 启动服务
- ./server &
- sleep 5
# 健康检查
- grpcurl -plaintext -d '{}' localhost:50051 grpc.health.v1.Health/Check
# 功能测试
- grpcurl -plaintext -d '{"name":"test"}' localhost:50051 helloworld.Greeter/SayHello
# 性能测试
- ghz --insecure --call helloworld.Greeter.SayHello -d '{"name":"test"}' -n 1000 localhost:50051
3. 调试技巧
# 查看详细错误信息
grpcurl -plaintext -v localhost:50051 helloworld.Greeter/SayHello
# 测试超时处理
grpcurl -plaintext -max-time 1s localhost:50051 helloworld.Greeter/SlowMethod
# 测试大消息
grpcurl -plaintext -d '{"data": "很长的数据..."}' localhost:50051 helloworld.Greeter/SayHello
# 查看服务端返回的元数据
grpcurl -plaintext -v localhost:50051 helloworld.Greeter/SayHello 2>&1 | grep -A 10 "Response headers"
小结
本章介绍了 gRPC 开发中常用的调试和测试工具:
- gRPC 反射:让工具自动发现服务定义
- grpcurl:命令行工具,适合脚本和自动化
- grpcui:Web 界面,适合手动调试
- ghz:性能测试工具,压测服务吞吐量
- 其他工具:grpc-health-probe、Postman 等
掌握这些工具可以显著提高 gRPC 开发效率。在开发环境启用反射,在生产环境使用 proto 文件或健康检查端点。
[!TIP] 生产环境不建议启用 gRPC 反射,因为它可能泄露服务接口信息。可以使用
-proto选项指定 proto 文件,或者使用健康检查端点。