Skip to content

如何使用 grpcurl 命令行工具测试你的 gRPC 服务 ​

如何使用 grpcurl 命令行工具测试你的 gRPC 服务示意图

像 curl 测试 HTTP 接口一样测试 gRPC 服务 —— grpcurl 工具完整教程


1. 什么是 grpcurl? ​

grpcurl 是一个命令行工具,用于与 gRPC 服务器进行交互。它的设计灵感来自 curl,但专门针对 gRPC 协议进行了优化。

核心功能 ​

功能说明
调用 gRPC 方法像 curl 调用 REST API 一样调用 gRPC 服务
服务发现通过 gRPC 反射自动获取服务定义
多协议支持支持 HTTP/2、TLS、Unix Socket
多种数据格式支持 JSON、Protobuf Text 格式
流式调用支持服务端流、客户端流、双向流

适用场景 ​

  • 开发阶段调试 gRPC 服务
  • 验证服务接口是否正常工作
  • 快速测试 API 返回结果
  • CI/CD 中的接口测试

2. 安装 grpcurl ​

方式一:使用 Go 安装(推荐) ​

bash
# 安装最新版本
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest

# 验证安装
~/go/bin/grpcurl --version

方式二:使用 Homebrew (macOS) ​

bash
brew update
brew install grpcurl
grpcurl --version

方式三:下载预编译二进制 ​

访问 GitHub Releases 下载对应平台的二进制文件。

bash
# 示例:下载 Linux amd64 版本
curl -L https://github.com/fullstorydev/grpcurl/releases/download/v1.9.3/grpcurl_1.9.3_linux_x86_64.tar.gz -o grpcurl.tar.gz
tar -xzf grpcurl.tar.gz
sudo mv grpcurl /usr/local/bin/

验证安装 ​

bash
grpcurl --version
# grpcurl 1.9.3

3. 基础用法 ​

3.1 查看服务列表 ​

bash
# 通过反射列出所有服务
grpcurl -plaintext localhost:50051 list

# 输出示例
# grpc.health.v1.Health
# grpc.reflection.v1alpha.ServerReflection
# discovery.v1.DiscoveryAgent

3.2 查看服务方法 ​

bash
# 列出特定服务的所有方法
grpcurl -plaintext localhost:50051 list discovery.v1.DiscoveryAgent

# 输出示例
# discovery.v1.DiscoveryAgent.Status
# discovery.v1.DiscoveryAgent.Heartbeat
# discovery.v1.DiscoveryAgent.Reload
# discovery.v1.DiscoveryAgent.Verify
# discovery.v1.DiscoveryAgent.StreamHeartbeat

3.3 查看方法详情 ​

bash
# 查看方法的请求/响应结构
grpcurl -plaintext localhost:50051 describe discovery.v1.DiscoveryAgent.Status

# 输出示例
# discovery.v1.DiscoveryAgent.Status is a method:
# rpc Status ( .discovery.v1.StatusRequest ) returns ( .discovery.v1.StatusResponse );

3.4 调用 gRPC 方法 ​

bash
# 无参数调用
grpcurl -plaintext localhost:50051 discovery.v1.DiscoveryAgent/Status

# 带参数调用
grpcurl -plaintext -d '{"timestamp": 1723456789}' localhost:50051 discovery.v1.DiscoveryAgent/Heartbeat

4. Unix Socket 调试(重点!) ​

4.1 版本差异 ​

不同版本的 grpcurl 对 Unix Socket 的支持方式不同:

版本正确格式说明
v1.8.7 及以下-unix /path/to/socket使用 -unix 标志
v1.9.0 及以上unix:///path/to/socket使用 URL 格式(推荐)

4.2 v1.9.0+ 的调用方式 ​

bash
# 基本格式:grpcurl [flags] [address] [service/method]
# address 格式:unix:///path/to/socket(三个斜杠)

# 基本调用
grpcurl -plaintext unix:///tmp/discovery-agent.sock discovery.v1.DiscoveryAgent/Status

# 带参数调用
grpcurl -plaintext -d '{"timestamp": 1723456789}' unix:///tmp/discovery-agent.sock discovery.v1.DiscoveryAgent/Heartbeat

# 无参调用
grpcurl -plaintext -d '{}' unix:///tmp/discovery-agent.sock discovery.v1.DiscoveryAgent/Reload

4.3 注意点 ​

要点说明
必须加 -plaintextUnix Socket 没有 TLS,不加会报 TLS 错误
地址格式必须使用 unix:///path/to/socket(三个斜杠)
-d 参数位置放在服务名前面
服务名格式package.Service/Method

4.4 常见错误及解决方案 ​

错误原因解决方案
missing port in address未使用 unix:// 格式使用 unix:///path/to/socket
first record does not look like a TLS handshake未加 -plaintext添加 -plaintext 标志
Too many arguments参数顺序或格式错误检查 -d 参数格式

5. 高级用法 ​

5.1 使用 -d @ 从标准输入读取 ​

当 JSON 数据较大或包含特殊字符时,可以使用 -d @ 从标准输入读取:

bash
# 使用 echo
echo '{"timestamp": 1723456789}' | grpcurl -plaintext -d @ unix:///tmp/discovery-agent.sock discovery.v1.DiscoveryAgent/Heartbeat

# 使用 here-document
grpcurl -plaintext -d @ unix:///tmp/discovery-agent.sock discovery.v1.DiscoveryAgent/Heartbeat <<EOF
{"timestamp": 1723456789}
EOF

# 从文件读取
grpcurl -plaintext -d @ unix:///tmp/discovery-agent.sock discovery.v1.DiscoveryAgent/Heartbeat < request.json

5.2 使用反射 vs 使用 proto 文件 ​

方式一:使用反射(推荐,需要服务端支持) ​

bash
grpcurl -plaintext localhost:50051 list
grpcurl -plaintext localhost:50051 describe discovery.v1.DiscoveryAgent

方式二:使用 proto 文件(反射不可用时) ​

bash
grpcurl -plaintext -proto api/v1/discovery.proto \
    -import-path ./api/v1 \
    localhost:50051 discovery.v1.DiscoveryAgent/Status

5.3 添加自定义 Header ​

bash
# 添加自定义 Header
grpcurl -plaintext -H "X-API-Key: abc123" \
    localhost:50051 discovery.v1.DiscoveryAgent/Status

# 添加多个 Header
grpcurl -plaintext -H "Authorization: Bearer token123" \
    -H "X-Request-ID: 12345" \
    localhost:50051 discovery.v1.DiscoveryAgent/Status

5.4 流式调用 ​

bash
# 服务端流(Server Streaming)
grpcurl -plaintext -d '{}' localhost:50051 package.Service/ServerStream

# 客户端流(Client Streaming)
grpcurl -plaintext -d @ localhost:50051 package.Service/ClientStream <<EOF
{"msg": "hello"}
{"msg": "world"}
EOF

6. 实用技巧 ​

6.1 格式化输出 ​

bash
# 使用 jq 美化输出
grpcurl -plaintext unix:///tmp/discovery-agent.sock discovery.v1.DiscoveryAgent/Status | jq .

# 只提取特定字段
grpcurl -plaintext unix:///tmp/discovery-agent.sock discovery.v1.DiscoveryAgent/Status | jq '.modules'

6.2 输出为 Protobuf Text 格式 ​

bash
grpcurl -format text -plaintext localhost:50051 discovery.v1.DiscoveryAgent/Status

6.3 调试请求/响应 ​

bash
# 启用详细输出
grpcurl -v -plaintext localhost:50051 discovery.v1.DiscoveryAgent/Status

# 查看请求/响应头
grpcurl -vv -plaintext localhost:50051 discovery.v1.DiscoveryAgent/Status

6.4 设置超时 ​

bash
# 连接超时 10 秒,总超时 30 秒
grpcurl -connect-timeout 10 -max-time 30 \
    -plaintext localhost:50051 discovery.v1.DiscoveryAgent/Status

7. 在 Makefile 中使用 ​

完整示例 ​

makefile
# grpcurl 测试命令
grpcurl-status:
	grpcurl -plaintext unix:///tmp/discovery-agent.sock discovery.v1.DiscoveryAgent/Status

grpcurl-heartbeat:
	grpcurl -plaintext -d '{"timestamp": 1723456789}' unix:///tmp/discovery-agent.sock discovery.v1.DiscoveryAgent/Heartbeat

grpcurl-reload:
	grpcurl -plaintext -d '{}' unix:///tmp/discovery-agent.sock discovery.v1.DiscoveryAgent/Reload

grpcurl-verify:
	grpcurl -plaintext -d '{"discovery_data": ""}' unix:///tmp/discovery-agent.sock discovery.v1.DiscoveryAgent/Verify

# 从文件读取数据的版本
grpcurl-heartbeat-file:
	grpcurl -plaintext -d @ unix:///tmp/discovery-agent.sock discovery.v1.DiscoveryAgent/Heartbeat < request.json

使用示例 ​

bash
make grpcurl-status
make grpcurl-heartbeat
make grpcurl-reload

8. 与 curl 对比 ​

功能curlgrpcurl
协议HTTP/1.1, HTTP/2HTTP/2 (gRPC)
数据格式JSON, XML, FormJSON, Protobuf
服务发现OpenAPI/SwaggergRPC 反射
Unix Socket--unix-socketunix:///path
流式❌✅ (双向流)
TLS✅✅

9. 常见问题 FAQ ​

Q1: grpcurl 报 Too many arguments ​

原因: 参数格式不正确。

解决方案:

  • 检查 -d 参数是否被正确解析
  • 使用 -d @ 从标准输入读取数据

Q2: Unix Socket 报 missing port in address ​

原因: 未使用正确的 Unix Socket 地址格式。

解决方案:

bash
# 正确格式(v1.9.0+)
grpcurl -plaintext unix:///tmp/socket.sock service/method

Q3: 报 first record does not look like a TLS handshake ​

原因: 未添加 -plaintext 标志。

解决方案:

bash
grpcurl -plaintext localhost:50051 service/method

Q4: 如何查看 grpcurl 版本? ​

bash
grpcurl --version

Q5: 服务端未启用反射怎么办? ​

使用 -proto 指定 proto 文件:

bash
grpcurl -plaintext -proto api/v1/service.proto -import-path ./api/v1 localhost:50051 package.Service/Method

10. 参考资源 ​

最后更新2026/07/15 08:34
如果你觉得这篇文章有帮助,或者想聊聊技术、工作,欢迎通过下面方式联系我:
contact fishfinal