那些年,我们用过的grpc调试工具
在我们的开发中越来越多使用grpc服务了,通常grpc使用的是protobuf协议,其优点:性能好/效率高,二进制编码,支持多语言;但可读性却很差,不像json那么直接明了。那么有没有一款工具,能够方便快速的进行开发调试呢?答案是有,还很多,而且我相信总有一款适合你!
先说结论:
喜欢web ui操作的,选择:grpcui
喜欢pc端操作的或者需要同时支持grpc和google api调试的,请选择bloomrpc
喜欢用命令行操作的,选择grpcurl,evans
调试模式
通常grpc调试的客户端都有两种模式:
- 使用proto描述文件进行调试
- 使用google.golang.org/grpc/reflection在运行时获取Proto定义信息的反射功能
两种模式使用场景和优缺点
- 使用proto文件进行调试,首先你要有这个文件,不然就干瞪眼了
- 使用reflection进行调试,首先要grpc服务端开启这个功能,不然你还是干瞪眼
- 在线上使用reflection且没有鉴权,很有可能影响线上数据安全
所以一般推荐使用proto文件进行调试
使用案例
proto文件:
syntax = "proto3";
package proto;
option go_package = "./api;qimaoPb";
service Say {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
repeated string names = 2;
}
message HelloReply {
string message = 1;
}
protoc命令生成:
protoc --go_out=. --go-grpc_out=. ./api/qimao.proto
server代码:
package main
import "fmt"
import "log"
import "net"
import "context"
import "jansonlv.top/coder/grpc/api"
import "google.golang.org/grpc"
import "google.golang.org/grpc/reflection"
func main() {
lis, err := net.Listen("tcp", ":8083")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
server := grpc.NewServer()
// 服务反射
reflection.Register(server)
qimaoPb.RegisterSayServer(server, &hello{})
if err := server.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
type hello struct {
qimaoPb.UnimplementedSayServer
}
func (*hello) SayHello(ctx context.Context, req *qimaoPb.HelloRequest) (*qimaoPb.HelloReply, error) {
log.Println(req)
message := "hello"
for _, name := range req.Names {
message += name + " "
}
reply := &qimaoPb.HelloReply{Message: message}
return reply, nil
}
代码结构如下:
tree:
.
├── api
│ ├── qimao.pb.go
│ ├── qimao.proto
│ └── qimao_grpc.pb.go
├── client
└── server
└── server.go
grpcurl
grpcurl是一个命令行工具,使用它可以在命令行中访问gRPC服务,就像使用curl
访问http服务一样。
安装
Mac:
brew install grpcurl
Linux
go get github.com/fullstorydev/grpcurl
go install github.com/fullstorydev/grpcurl/cmd/grpcurl
使用
反射模式
查看服务列表:
~ grpcurl -plaintext 127.0.0.1:8083 list
grpc.reflection.v1alpha.ServerReflection
proto.Say
查看某个服务的方法列表:
~ grpcurl -plaintext 127.0.0.1:8083 list proto.Say
proto.Say.SayHello
查看方法定义:
~ grpcurl -plaintext 127.0.0.1:8083 describe proto.Say.SayHello
proto.Say.SayHello is a method:
rpc SayHello ( .proto.HelloRequest ) returns ( .proto.HelloReply );
查看请求定义:
~ grpcurl -plaintext 127.0.0.1:8083 describe proto.HelloRequest
proto.HelloRequest is a message:
message HelloRequest {
string name = 1;
repeated string names = 2;
}
调用服务,参数传json即可:
grpcurl -d '{"name": "abc"}' -plaintext 127.0.0.1:8083 proto.Say.SayHello
{
"message": "hello"
}
grpcurl -d '{"name": "abc", "names":["1","2"]}' -plaintext 127.0.0.1:8083 proto.Say.SayHello
{
"message": "hello1 2 "
}
proto文件
首先查看服务列表:
~ grpcurl -proto=api/qimao.proto -plaintext 127.0.0.1:8083 list
proto.Say
其他操作也和使用反射一样的
感受
grpcurl这个工具从使用上十分简单,通过list和describe基本可以查看proto文件的内容,通过这些命令最终请求到参数
但是在proto文件中service、方法以及message很多的情况下,使用起来就很方便,那么有没有什么ui工具,可以一目了然的使用呢?
grpcui
额,这个完全和grpcurl就是兄弟两个,但是grpcui使用起来也更方便,毕竟有web界面啊
安装
参考grpcurl,把rl换成i接口
使用
使用反射和proto文件进行调试,命令和grpcurl都一样,效果也是一样的,我们就使用proto文件来看看功能:
~ grpcui -proto api/qimao.proto -plaintext 127.0.0.1:8083
gRPC Web UI available at http://127.0.0.1:54358/
grpcui服务启动一个web服务提供给我们,打开该地址
到这,我们就可以看到service name,method name还有请求参数,只要点点输入参数并进行invoke请求就可以了,是不是很方便
感受
使用很方便,参数,方法一目了然,勾勾填填即可发起请求,也可以使用json格式进行数据发送,支持历史数据回放等功能,赞
bloomrpc
安装
github:bloomrpc
使用
感受
优点:
- 支持文件重载,方便proto有更新的时候直接加载,无需重启
- 支持env环境切换
- 支持web和grpc切换
- 可以多项目的proto文件管理和请求,只要设置响应的env即可
- 客户端流和双向流支持
- 支持多tab页使用
缺点:
- 需要下载客户端使用
- 不支持反射模式
总而言之,也是一个功能齐全完善的工具
evans
安装
$ brew tap ktr0731/evans
$ brew install evans
使用
Evans有两种运行模式:REPL
和CLI
CLI模式
使用反射模式
$ evans -r --port=8083 cli list
grpc.reflection.v1alpha.ServerReflection
proto.Say
使用proto文件模式
$ evans --port=8083 --proto=api/qimao.proto cli list
proto.Say
用起来很像grpcurl
REPL模式
$ evans --port=8083 api/qimao.proto
______
| ____|
| |__ __ __ __ _ _ __ ___
| __| \ \ / / / _. | | '_ \ / __|
| |____ \ V / | (_| | | | | | \__ \
|______| \_/ \__,_| |_| |_| |___/
more expressive universal gRPC client
proto.Say@127.0.0.1:8083>
默认指定proto,当然也可以使用-r使用反射模式进入该模式
展示pb包名
proto.Say@127.0.0.1:8083> show package
+---------+
| PACKAGE |
+---------+
| proto |
+---------+
展示服务名
proto.Say@127.0.0.1:8083> show service
+---------+----------+--------------+---------------+
| SERVICE | RPC | REQUEST TYPE | RESPONSE TYPE |
+---------+----------+--------------+---------------+
| Say | SayHello | HelloRequest | HelloReply |
+---------+----------+--------------+---------------+
服务调用
proto.Say@127.0.0.1:8083> call SayHello
name (TYPE_STRING) => 1
<repeated> names (TYPE_STRING) => 1
<repeated> names (TYPE_STRING) => 2
<repeated> names (TYPE_STRING) => 3
<repeated> names (TYPE_STRING) => 4
age (TYPE_INT64) =>
{
"message": "hello1 2 3 4 "
}
这里有个注意点:repeated数组是不知道什么时候结束的,可以一直输入,所以想要停止,需要CTRL-D
进行停止,如果一个字段不想输入的话,可以使用CTRL-C
跳过。
还有一些其他的功能,可以使用evans -h
去帮助说明
感受
优点:
- REPL交互模式体验感很好,有操作提示
- 支持三种流式操作
注意
如果使用gogoprotobuf生成的代码,虽然接口请求兼容google protobuf,但是反射是不支持,无法使用反射进行调试,只能使用proto文件进行调试。
Reference:
https://github.com/fullstorydev/grpcui
https://github.com/ktr0731/evans
https://github.com/uw-labs/bloomrpc
https://blog.frognew.com/2020/04/grpcurl.html
https://chai2010.gitbooks.io/advanced-go-programming-book/content/ch4-rpc/ch4-08-grpcurl.html