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: grpcurlToo 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