跳到主要内容

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 界面,你可以:

  1. 浏览所有服务和方法
  2. 查看消息类型定义
  3. 填写请求参数
  4. 执行调用并查看响应

常用选项

# 指定绑定端口
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 对比

特性grpcurlgrpcui
界面命令行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:

  1. 创建新的 gRPC 请求
  2. 输入服务器地址
  3. 加载 proto 文件或使用反射
  4. 选择方法并发送请求

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 开发中常用的调试和测试工具:

  1. gRPC 反射:让工具自动发现服务定义
  2. grpcurl:命令行工具,适合脚本和自动化
  3. grpcui:Web 界面,适合手动调试
  4. ghz:性能测试工具,压测服务吞吐量
  5. 其他工具:grpc-health-probe、Postman 等

掌握这些工具可以显著提高 gRPC 开发效率。在开发环境启用反射,在生产环境使用 proto 文件或健康检查端点。

[!TIP] 生产环境不建议启用 gRPC 反射,因为它可能泄露服务接口信息。可以使用 -proto 选项指定 proto 文件,或者使用健康检查端点。