golang更强大的通用gRPC客户端工具插件evans的使用

Golang 更强大的通用 gRPC 客户端工具插件 Evans 的使用

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

1 回复

更多关于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"]

实用技巧

  1. JSON 格式化输出

    evans --format json -p 50051 --proto service.proto
    
  2. 调试模式

    evans --debug -p 50051
    
  3. 导出调用历史

    history --save commands.txt
    
  4. 使用环境变量

    export EVANS_HEADER="Authorization=Bearer token123"
    evans -p 50051
    

Evans 是一个功能全面的 gRPC 客户端工具,特别适合在开发阶段测试和调试 gRPC 服务。它的交互式 REPL 环境和自动补全功能可以显著提高开发效率。

回到顶部