gRPC之grpcurl

1、grpcurl

grpcurl项目地址 :https://github.com/fullstorydev/grpcurl

一般情况下测试 gRPC 服务,都是通过客户端来直接请求服务端。如果客户端还没准备好的话,也可以使用

BloomRPC (https://appimage.github.io/BloomRPC/)这样的 GUI 客户端。

如果环境不支持安装这种GUI客户端的话,那么有没有一种工具,类似于 curl 这样的,直接通过终端,在命令

行发起请求呢?答案肯定是有的,就是本文要介绍的 grpcurl

grpcurl是一个命令行工具,使用它可以在命令行中访问gRPC服务,就像使用curl访问http服务一样。

下面通过一个案例来展示grpcurl的使用。

1.1 在gRPC服务中注册reflection服务

gRPC服务是使用Protobuf(PB)协议的,而PB提供了在运行时获取Proto定义信息的反射功能。

grpc-go https://github.com/grpc/grpc-go中的google.golang.org/grpc/reflection

http://google.golang.org/grpc/reflection包就对这个反射功能提供了支持。

1.2 编写proto

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;
}

1.3 编译proto

$ protoc -I . --go_out=plugins=grpc:. ./hello.proto

1.4 服务端

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

1.5 grpcurl 安装

如果有 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>

1.6 grpcurl 使用

在使用 grpcurl 时,需要通过 -cert-key 参数设置公钥和私钥文件,表示链接启用了TLS协议的服务。

对于没有启用TLS协议的 gRPC 服务,通过 -plaintext 参数忽略 TLS 证书的验证过程。

如果是 Unix Socket 协议,则需要指定 -unix 参数。

1.6.1 查看服务列表
$ 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
1.6.2 查看某个服务的方法列表
$ 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
1.6.3 查看方法定义
$ 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 );
1.6.4 查看请求参数
$ 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;
}
1.6.5 请求服务
$ 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"
}

1.7 可能遇到的错误

可能会遇到四个报错:

1.7.1 gRPC Server 未启用 TLS

报错信息:

Failed to dial target host "127.0.0.1:50051": tls: first record does not look like a TLS handshake

解决:

请求时增加参数:-plaintext,参考上面的命令。

1.7.2 服务没有启动 reflection 反射服务

报错信息:

Failed to list services: server does not support the reflection API

解决:

这行代码是关键,一定要包含:

// 注册grpcurl所需的reflection服务
reflection.Register(server)
1.7.3 参数格式错误

报错信息:

Error invoking method "greet.Greeter/SayHello": error getting request data: invalid character 'n' looking for beginning of object key string

解决:

-d 后面参数为 json 格式,并且需要使用 '' 包裹起来。

1.7.4 参数太多
Too many arguments.
Try 'grpcurl -help' for more details.

解决:

grpcurl -plaintext -d "{\"name\":\"rao\"}" 127.0.0.1:50051 proto.Greeter/SayHello

1.8 总结

grpcurl这个工具从使用上十分简单,查看服务信息基本上类似展示的proto文件的内容,调用服务这个功能还是很

实用的,可以整合到k8s的Pod镜像中,用于在k8s集群内部简单测试gRPC服务。

你可能感兴趣的:(gRPC,gRPC)