那些年,我们用过的grpc调试工具

在我们的开发中越来越多使用grpc服务了,通常grpc使用的是protobuf协议,其优点:性能好/效率高,二进制编码,支持多语言;但可读性却很差,不像json那么直接明了。那么有没有一款工具,能够方便快速的进行开发调试呢?答案是有,还很多,而且我相信总有一款适合你!

先说结论:

喜欢web ui操作的,选择:grpcui

喜欢pc端操作的或者需要同时支持grpc和google api调试的,请选择bloomrpc

喜欢用命令行操作的,选择grpcurl,evans

调试模式

通常grpc调试的客户端都有两种模式:

  1. 使用proto描述文件进行调试
  2. 使用google.golang.org/grpc/reflection在运行时获取Proto定义信息的反射功能

两种模式使用场景和优缺点

  1. 使用proto文件进行调试,首先你要有这个文件,不然就干瞪眼了
  2. 使用reflection进行调试,首先要grpc服务端开启这个功能,不然你还是干瞪眼
  3. 在线上使用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

使用

感受

优点:

  1. 支持文件重载,方便proto有更新的时候直接加载,无需重启
  2. 支持env环境切换
  3. 支持web和grpc切换
  4. 可以多项目的proto文件管理和请求,只要设置响应的env即可
  5. 客户端流和双向流支持
  6. 支持多tab页使用

缺点:

  1. 需要下载客户端使用
  2. 不支持反射模式

总而言之,也是一个功能齐全完善的工具

evans

安装

$ brew tap ktr0731/evans
$ brew install evans

使用

Evans有两种运行模式:REPLCLI

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去帮助说明

感受

优点:

  1. REPL交互模式体验感很好,有操作提示
  2. 支持三种流式操作

注意

如果使用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

https://mp.weixin.qq.com/s/dG49wTV2UAXQUC-KQ9ggBA