grpcurl
项目地址 :https://github.com/fullstorydev/grpcurl
一般情况下测试 gRPC 服务,都是通过客户端来直接请求服务端。如果客户端还没准备好的话,也可以使用
BloomRPC
(https://appimage.github.io/BloomRPC/
)这样的 GUI 客户端。
如果环境不支持安装这种GUI客户端的话,那么有没有一种工具,类似于 curl
这样的,直接通过终端,在命令
行发起请求呢?答案肯定是有的,就是本文要介绍的 grpcurl
。
grpcurl
是一个命令行工具,使用它可以在命令行中访问gRPC服务,就像使用curl
访问http服务一样。
下面通过一个案例来展示grpcurl的使用。
gRPC服务是使用Protobuf(PB)协议的,而PB提供了在运行时获取Proto定义信息的反射功能。
grpc-go
https://github.com/grpc/grpc-go
中的google.golang.org/grpc/reflection
http://google.golang.org/grpc/reflection
包就对这个反射功能提供了支持。
hello.proto
文件的内容:
syntax = "proto3";
package proto;
option go_package = "./proto;proto";
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
$ protoc -I . --go_out=plugins=grpc:. ./hello.proto
server.go
内容如下:
package main
import (
"context"
"fmt"
"demo/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"log"
"net"
)
type greeter struct {
}
func (*greeter) SayHello(ctx context.Context, req *proto.HelloRequest) (*proto.HelloReply, error) {
fmt.Println(req)
reply := &proto.HelloReply{Message: "hello"}
return reply, nil
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
server := grpc.NewServer()
// 注册 grpcurl 所需的 reflection 服务
reflection.Register(server)
// 注册业务服务
proto.RegisterGreeterServer(server, &greeter{})
fmt.Println("grpc server start ...")
if err := server.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
在main.go
中使用reflection.Register(server)
注册了reflection
服务。
运行服务:
[root@zsx demo]# go run server.go
grpc server start ...
# 项目结构
$ tree demo/
demo/
├── go.mod
├── go.sum
├── hello.proto
├── proto
│ └── hello.pb.go
├── request.json
└── server.go
1 directory, 6 files
如果有 Go 环境的话,可以通过 go tool 来安装:
# $ go install github.com/fullstorydev/grpcurl/cmd/grpcurl
$ go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
$ grpcurl -version
grpcurl dev build <no version set>
在使用 grpcurl 时,需要通过 -cert
和 -key
参数设置公钥和私钥文件,表示链接启用了TLS
协议的服务。
对于没有启用TLS
协议的 gRPC 服务,通过 -plaintext
参数忽略 TLS 证书的验证过程。
如果是 Unix Socket 协议,则需要指定 -unix
参数。
$ grpcurl -plaintext 127.0.0.1:50051 list
输出:
[root@zsx demo]# grpcurl -plaintext 127.0.0.1:50051 list
grpc.reflection.v1alpha.ServerReflection
proto.Greeter
$ grpcurl -plaintext 127.0.0.1:50051 list proto.Greeter
输出:
[root@zsx demo]# grpcurl -plaintext 127.0.0.1:50051 list proto.Greeter
proto.Greeter.SayHello
$ grpcurl -plaintext 127.0.0.1:50051 describe proto.Greeter.SayHello
输出:
[root@zsx demo]# grpcurl -plaintext 127.0.0.1:50051 describe proto.Greeter.SayHello
proto.Greeter.SayHello is a method:
rpc SayHello ( .proto.HelloRequest ) returns ( .proto.HelloReply );
$ grpcurl -plaintext 127.0.0.1:50051 describe proto.HelloRequest
输出:
[root@zsx demo]# grpcurl -plaintext 127.0.0.1:50051 describe proto.HelloRequest
proto.HelloRequest is a message:
message HelloRequest {
string name = 1;
}
$ grpcurl -plaintext -d "{\"name\":\"rao\"}" 127.0.0.1:50051 proto.Greeter/SayHello
输出:
[root@zsx demo]# grpcurl -plaintext -d "{\"name\":\"rao\"}" 127.0.0.1:50051 proto.Greeter/SayHello
{
"message": "hello"
}
-d
参数后面也可以跟 @
,表示从标准输入读取 json 参数,一般用于输入比较复杂的 json 数据,也可以用于测试
流方法。
$ cat request.json | grpcurl -d @ -plaintext 127.0.0.1:50051 proto.Greeter.SayHello
输出:
[root@zsx demo]# cat request.json | grpcurl -d @ -plaintext 127.0.0.1:50051 proto.Greeter.SayHello
{
"message": "hello"
}
可能会遇到四个报错:
报错信息:
Failed to dial target host "127.0.0.1:50051": tls: first record does not look like a TLS handshake
解决:
请求时增加参数:-plaintext
,参考上面的命令。
报错信息:
Failed to list services: server does not support the reflection API
解决:
这行代码是关键,一定要包含:
// 注册grpcurl所需的reflection服务
reflection.Register(server)
报错信息:
Error invoking method "greet.Greeter/SayHello": error getting request data: invalid character 'n' looking for beginning of object key string
解决:
-d
后面参数为 json 格式,并且需要使用 ''
包裹起来。
Too many arguments.
Try 'grpcurl -help' for more details.
解决:
grpcurl -plaintext -d "{\"name\":\"rao\"}" 127.0.0.1:50051 proto.Greeter/SayHello
grpcurl这个工具从使用上十分简单,查看服务信息基本上类似展示的proto文件的内容,调用服务这个功能还是很
实用的,可以整合到k8s的Pod镜像中,用于在k8s集群内部简单测试gRPC服务。