golang更强大的通用gRPC客户端工具插件evans的使用
Golang 更强大的通用 gRPC 客户端工具插件 Evans 的使用
动机
Evans 的创建是为了比其他现有的 gRPC 客户端更容易使用。如果你想保持产品质量,你应该使用 CI 进行 gRPC 测试,而不应该进行手动测试。Evans 将完成你的其他用例,如:
- 手动检查 gRPC API
- 通过脚本自动化某些任务
上述用例对应于 Evans 的两种模式:REPL 模式和 CLI 模式。
REPL 模式
REPL 模式是第一个用例的解决方案。你可以无需考虑包名、服务名、RPC 名、命令用法等,因为 REPL 模式具有强大的自动补全功能!
CLI 模式
CLI 模式是一个无状态模式,就像 grpc-ecosystem/polyglot。如其名称所示,它每个命令发送一个请求。因此它基于 UNIX 哲学。
例如,从 stdin 读取输入,命令将是一个过滤器命令。另一方面,命令结果将以 JSON 格式输出到 stdout。因此,你可以使用任何命令(如 jq)来格式化它。此外,如果你想使用相同的命令(例如使用相同的 JSON 输入),你可以使用 --file (-f) 选项。
安装
从 GitHub Releases 安装
可用的二进制文件包括:
- macOS
- Linux
- Windows
macOS
brew tap ktr0731/evans
brew install evans
Docker 镜像
例如,如果你想使用 ./proto/files/file-name.proto 中的 proto 文件连接到主机 example.com 上的服务器,端口为 50051(默认工作目录为 /mount):
$ docker run --rm -v "$(pwd):/mount:ro" \
ghcr.io/ktr0731/evans:latest \
--path ./proto/files \
--proto file-name.proto \
--host example.com \
--port 50051 \
repl
[不推荐] go install
需要 Go v1.20 或更高版本。
go install github.com/ktr0731/evans@latest
使用 (REPL)
基本用法
Evans 在 REPL 模式下由一些命令组成。
进入 REPL:
cd grpc-test
evans --proto api/api.proto repl
如果你的服务器启用了 gRPC 反射,你可以仅使用 -r (–reflection) 选项启动 Evans。
evans -r repl
此外,如果服务器需要安全的 TLS 连接,你可以使用 -t (–tls) 选项启动 Evans。
evans --tls --host example.com -r repl
显示 proto 文件的包名:
> show package
+---------+
| PACKAGE |
+---------+
| api |
+---------+
显示服务或消息的摘要:
> package api
> show service
+---------+----------------------+-----------------------------+----------------+
| SERVICE | RPC | REQUESTTYPE | RESPONSETYPE |
+---------+----------------------+-----------------------------+----------------+
| Example | Unary | SimpleRequest | SimpleResponse |
| | UnaryMessage | UnaryMessageRequest | SimpleResponse |
| | UnaryRepeated | UnaryRepeatedRequest | SimpleResponse |
| | UnaryRepeatedMessage | UnaryRepeatedMessageRequest | SimpleResponse |
| | UnaryRepeatedEnum | UnaryRepeatedEnumRequest | SimpleResponse |
| | UnarySelf | UnarySelfRequest | SimpleResponse |
| | UnaryMap | UnaryMapRequest | SimpleResponse |
| | UnaryMapMessage | UnaryMapMessageRequest | SimpleResponse |
| | UnaryOneof | UnaryOneofRequest | SimpleResponse |
| | UnaryEnum | UnaryEnumRequest | SimpleResponse |
| | UnaryBytes | UnaryBytesRequest | SimpleResponse |
| | ClientStreaming | SimpleRequest | SimpleResponse |
| | ServerStreaming | SimpleRequest | SimpleResponse |
| | BidiStreaming | SimpleRequest | SimpleResponse |
+---------+----------------------+-----------------------------+----------------+
> show message
+-----------------------------+
| MESSAGE |
+-----------------------------+
| SimpleRequest |
| SimpleResponse |
| Name |
| UnaryMessageRequest |
| UnaryRepeatedRequest |
| UnaryRepeatedMessageRequest |
| UnaryRepeatedEnumRequest |
| UnarySelfRequest |
| Person |
| UnaryMapRequest |
| UnaryMapMessageRequest |
| UnaryOneofRequest |
| UnaryEnumRequest |
| UnaryBytesRequest |
+-----------------------------+
显示消息的更多描述:
> desc SimpleRequest
+-------+-------------+
| FIELD | TYPE |
+-------+-------------+
| name | TYPE_STRING |
+-------+-------------+
为每个请求设置头部:
> header foo=bar
显示头部:
> show header
+-------------+-------+
| KEY | VAL |
+-------------+-------+
| foo | bar |
| grpc-client | evans |
+-------------+-------+
注意:如果你想将包含逗号的字符串设置为头部值,需要指定 --raw 选项。
删除添加的头部:
> header foo
> show header
+-------------+-------+
| KEY | VAL |
+-------------+-------+
| grpc-client | evans |
+-------------+-------+
调用 RPC:
> service Example
> call Unary
name (TYPE_STRING) => ktr
{
"message": "hello, ktr"
}
Evans 交互式地构建 gRPC 请求并将其发送到 gRPC 服务器。最后,Evans 打印 JSON 格式的结果。
重复字段
repeated 是一个类似数组的数据结构。你可以输入一些值并以 CTRL-D 结束。
> call UnaryRepeated
<repeated> name (TYPE_STRING) => foo
<repeated> name (TYPE_STRING) => bar
<repeated> name (TYPE_STRING) => baz
<repeated> name (TYPE_STRING) =>
{
"message": "hello, foo, bar, baz"
}
枚举字段
你可以从提议的选择中选择一个。当输入 CTRL-C 时,将使用默认值 0。当输入 CTRL-D 时,输入将被中止。
> call UnaryEnum
? UnaryEnumRequest [Use arrows to move, type to filter]
> Male
Female
{
"message": "M"
}
字节类型字段
你需要将字节编码为 Base64。
> call UnaryBytes
data (TYPE_BYTES) => SGVsbG8gV29ybGQh
{
"message": "received: (bytes) 48 65 6c 6c 6f 20 57 6f 72 6c 64 21, (string) Hello World!"
}
⚠️ 警告:以前,字节作为(引用的)字节字面量或 Unicode 字面量字符串传递。虽然 Evans 目前仍然尝试在解码为 base64 失败时回退到该编码,但不推荐这样做,可能会被删除。
请将字节编码为 base64,或显式传递 --bytes-as-quoted-literals:
> call UnaryBytes --bytes-as-quoted-literals
data (TYPE_BYTES) => \x46\x6f\x6f
{
"message": "received: (bytes) 46 6f 6f, (string) Foo"
}
> call UnaryBytes --bytes-as-quoted-literals
data (TYPE_BYTES) => \u65e5\u672c\u8a9e
{
"message": "received: (bytes) e6 97 a5 e6 9c ac e8 aa 9e, (string) 日本語"
}
你也可以添加标志 --bytes-from-file 从提供的相对路径读取字节:
> call UnaryBytes --bytes-from-file
data (TYPE_BYTES) => ../relative/path/to/file
客户端流式 RPC
客户端流式 RPC 接受一些请求,然后只返回一个响应。以 CTRL-D 结束请求输入。
> call ClientStreaming
name (TYPE_STRING) => ktr
name (TYPE_STRING) => ktr
name (TYPE_STRING) => ktr
name (TYPE_STRING) =>
{
"message": "ktr, you greet 3 times."
}
服务器流式 RPC
服务器流式 RPC 只接受一个请求,然后返回一些响应。每个响应表示为另一个 JSON 格式的输出。
name (TYPE_STRING) => ktr
{
"message": "hello ktr, I greet 0 times."
}
{
"message": "hello ktr, I greet 1 times."
}
双向流式 RPC
双向流式 RPC 接受一些请求并返回对应于每个请求的一些响应。以 CTRL-D 结束请求输入。
> call BidiStreaming
name (TYPE_STRING) => foo
{
"message": "hello foo, I greet 0 times."
}
{
"message": "hello foo, I greet 1 times."
}
{
"message": "hello foo, I greet 2 times."
}
name (TYPE_STRING) => bar
{
"message": "hello bar, I greet 0 times."
}
name (TYPE_STRING) =>
跳过其余字段
Evans 将 CTRL-C 识别为跳过当前消息类型中其余字段的特殊键。例如,我们假设我们正在输入以下消息中描述的 Request:
message FullName {
string first_name = 1;
string last_name = 2;
}
message Request {
string nickname = 1;
FullName full_name = 2;
}
如果我们在以下时刻输入 CTRL-C,full_name 字段将被跳过。
nickname (TYPE_STRING) =>
实际的请求值就像这样。
{}
如果我们在以下时刻
更多关于golang更强大的通用gRPC客户端工具插件evans的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang更强大的通用gRPC客户端工具插件evans的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用 Evans - 强大的通用 gRPC 客户端工具
Evans 是一个功能丰富的 gRPC 客户端工具,比标准的 grpc_cli
更强大且用户友好。它支持交互式 REPL 环境、自动补全、彩色输出等功能,非常适合开发和调试 gRPC 服务。
安装 Evans
# 使用 Go 安装
go install github.com/ktr0731/evans@latest
# 或者使用 Homebrew (macOS/Linux)
brew tap ktr0731/evans
brew install evans
基本使用
1. 连接到 gRPC 服务
# 连接到本地服务
evans -r repl -p 50051
# 使用反射服务
evans --host localhost --port 50051 --reflection
# 使用 proto 文件
evans -p 50051 --path ./api/proto --proto service.proto
2. 交互式 REPL 环境
进入 REPL 后,可以执行以下操作:
# 列出所有服务
show service
# 选择服务
package mypackage
service MyService
# 列出服务方法
show method
# 调用方法
call MyMethod
高级功能
1. 自动补全
Evans 提供强大的自动补全功能,包括:
- 服务名补全
- 方法名补全
- 请求消息字段补全
- 枚举值补全
2. 请求示例
# 调用 Unary RPC
call GetUser
:: 输入请求参数 (JSON 格式)
{
"id": "123"
}
# 调用服务端流式 RPC
call ListUsers
:: 输入请求参数
{
"page": 1,
"page_size": 10
}
# 调用客户端流式 RPC
call UploadUsers
:: 多次输入消息
{
"name": "Alice",
"email": "alice@example.com"
}
:: 按 Ctrl+D 结束输入
# 调用双向流式 RPC
call Chat
:: 交互式输入消息
3. 元数据/头部操作
# 添加头部
header X-Request-ID=12345
header Authorization=Bearer token123
# 查看当前头部
show header
# 清除头部
header --clear
4. 脚本模式
可以编写脚本自动化执行命令:
echo 'call GetUser {"id":"123"}' | evans -r cli -p 50051 --proto service.proto
Golang 集成示例
虽然 Evans 主要是命令行工具,但可以在 Go 测试中集成使用:
package main
import (
"fmt"
"os/exec"
"testing"
)
func TestGRPCCallViaEvans(t *testing.T) {
cmd := exec.Command("evans", "-r", "cli", "-p", "50051", "--proto", "service.proto", "--", "call", "GetUser", `{"id":"123"}`)
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("Evans command failed: %v\nOutput: %s", err, output)
}
fmt.Printf("Response: %s\n", output)
// 在这里解析输出并验证结果
}
配置文件支持
Evans 支持配置文件 ~/.evans.toml
:
[default]
host = "localhost"
port = 50051
header = ["X-Request-ID:12345"]
reflection = true
path = ["./proto"]
proto = ["service.proto"]
实用技巧
-
JSON 格式化输出:
evans --format json -p 50051 --proto service.proto
-
调试模式:
evans --debug -p 50051
-
导出调用历史:
history --save commands.txt
-
使用环境变量:
export EVANS_HEADER="Authorization=Bearer token123" evans -p 50051
Evans 是一个功能全面的 gRPC 客户端工具,特别适合在开发阶段测试和调试 gRPC 服务。它的交互式 REPL 环境和自动补全功能可以显著提高开发效率。