[gRPC] grpcurl 使用指南

Github 地址

介绍

grpcurl 是一个能够直接与 gRPC 服务交互的命令行工具。基本算是 curl 的 gRPC 版本。由于 gRPC 服务之间的通信使用的是 protocol buffers(下文 PB 指代) 格式的二进制编码,所以无法使用传统的 curl ,更何况旧版本的 curl 还不支持 HTTP/2。为了更好上手,该工具和服务器交互时我们只需要提供 JSON 数据作为请求数据即可,该工具底层会自动将其编码为 PB 格式的二进制与服务端进行交互。

该工具支持通过以下几种情况查看 gPRC service 的定义格式(schema):

只有通过使用上述方式查询得到的 schema,该工具才能能够将 JSON 请求数据准确的转换成 PB 格式的二进制数据。

grpcurl 项目(github.com/fullstorydev/grpcurl)同时可以作为 lib 使用。这个 lib 提供了比其他工具更加简化的寻址功能。同时该项目是使用 protoreflect 的一个经典案例。

特点

  1. grpcurl 支持所有 gRPC 的方法,包括 stream 方法。通过 grpcurl 你甚至可以与服务端进行双向的 stram 交流。
  2. grpcurl 支持 plain-text(HTTP/2) 及 TLS, 对于 TLS 有大量的可选项配置,同时支持双向 TLS 即当客户端被要求提交证书也是支持的。
  3. 如上文提到的,grpcurl 支持通过反射服务无缝连接,又或者使用 proto 或则 protoset 文件。

安装

  1. 直接下载进行安装,访问 releases 即可。
  2. mac 平台通过 Homebrew 方式安装
% brew install grpcurl
  1. 源码方式安装详见 from-source

使用

使用文档帮助:

% grpcurl -help

案例1 查看指定项目提供的所有服务

假设服务端支持如下服务:

syntax = "proto3";

package grpc.examples.echo;

option go_package = "google.golang.org/grpc/examples/features/proto/echo";

// EchoRequest is the request for echo.
message EchoRequest {
  string message = 1;
}

// EchoResponse is the response for echo.
message EchoResponse {
  string message = 1;
}

// Echo is the echo service.
service Echo {
  // UnaryEcho is unary echo.
  rpc UnaryEcho(EchoRequest) returns (EchoResponse) {}
  // ServerStreamingEcho is server side streaming.
  rpc ServerStreamingEcho(EchoRequest) returns (stream EchoResponse) {}
  // ClientStreamingEcho is client side streaming.
  rpc ClientStreamingEcho(stream EchoRequest) returns (EchoResponse) {}
  // BidirectionalStreamingEcho is bidi streaming.
  rpc BidirectionalStreamingEcho(stream EchoRequest) returns (stream EchoResponse) {}
}

成功运行 服务端代码 后(默认运行在了 50051 端口),通过下述命令可以查看其支持的所有服务:

% grpcurl -plaintext 127.0.0.1:50051 list                                 
grpc.examples.echo.Echo
grpc.reflection.v1alpha.ServerReflection

help 的说明如下

If ‘list’ is indicated, the symbol (if present) should be a fully-qualified service name. If present, all methods of that service are listed. If not present, all exposed services are listed, or all services defined in protosets

-plaintext :

Use plain-text HTTP/2 when connecting to server (no TLS)

即上面的命令我们通过 HTTP/2 的方式与 gRPC 服务端进行了一次交互,查询了其支持的所有的 service,其中就包括前面定义的 proto 内容 grpc.examples.echo.Echo

grpc.reflection.v1alpha.ServerReflection service 是由服务端使用了反射服务所生成。

亦或者我们可以直接加载 proto 文件的方式查看所支持的服务:

% grpcurl -import-path echo -proto echo.proto list
grpc.examples.echo.Echo

help 的说明如下

-import-path value :

The path to a directory from which proto sources can be imported, for use with -proto flags. Multiple import paths can be configured by specifying multiple -import-path flags. Paths will be searched in the order given. If no import paths are given, all files (including all imports) must be provided as -proto flags, and grpcurl will attempt to resolve all import statements from the set of file names given.

-proto value :

The name of a proto source file. Source files given will be used to determine the RPC schema instead of querying for it from the remote server via the gRPC reflection API. When set: the ‘list’ action lists the services found in the given files and their imports (vs. those exposed by the remote server), and the ‘describe’ action describes symbols found in the given files. May specify more than one via multiple -proto flags. Imports will be resolved using the given -import-path flags. Multiple proto files can be specified by specifying multiple -proto flags. It is an error to use both -protoset and -proto flags.

由于上面的命令不是使用服务端的反射服务进行查询,而是使用的 proto 源文件进行加载查询得出,故只有一项 grpc.examples.echo.Echo

案例2 查看指定服务支持的方法

在前面使用 list 的基础上,我们还可以进一步查询指定服务所支持的方法:

% grpcurl -plaintext 127.0.0.1:50051 list grpc.examples.echo.Echo
grpc.examples.echo.Echo.BidirectionalStreamingEcho
grpc.examples.echo.Echo.ClientStreamingEcho
grpc.examples.echo.Echo.ServerStreamingEcho
grpc.examples.echo.Echo.UnaryEcho

同理,使用 proto 文件方式也可以得到一样的输出:

% grpcurl -import-path ./echo -proto echo.proto list grpc.examples.echo.Echo
grpc.examples.echo.Echo.BidirectionalStreamingEcho
grpc.examples.echo.Echo.ClientStreamingEcho
grpc.examples.echo.Echo.ServerStreamingEcho
grpc.examples.echo.Echo.UnaryEcho

案例3 获取指定服务的描述信息

前面两个案例我们使用 list 只是查看到了相应的服务名,如果需要查看更具体的描述则需要通过 describe。

% grpcurl -plaintext 127.0.0.1:50051 describe grpc.examples.echo.Echo     
grpc.examples.echo.Echo is a service:
service Echo {
  rpc BidirectionalStreamingEcho ( 
  	stream .grpc.examples.echo.EchoRequest ) returns ( 
  	stream .grpc.examples.echo.EchoResponse );

  rpc ClientStreamingEcho ( 
  	stream .grpc.examples.echo.EchoRequest ) returns ( 
  	.grpc.examples.echo.EchoResponse );

  rpc ServerStreamingEcho ( 
  	.grpc.examples.echo.EchoRequest ) returns ( 
  	stream .grpc.examples.echo.EchoResponse );

  rpc UnaryEcho ( 
  	.grpc.examples.echo.EchoRequest ) returns ( 
  	.grpc.examples.echo.EchoResponse );
}

由于代码不能横向拖动导致展示不美观,这里加了些换行缩进。同理,使用加载 proto 文件方式也可以得到一样的输出:

% grpcurl -import-path ./echo -proto echo.proto describe grpc.examples.echo.Echo
grpc.examples.echo.Echo is a service:
// Echo is the echo service.
service Echo {
  // BidirectionalStreamingEcho is bidi streaming.
  rpc BidirectionalStreamingEcho ( 
  	stream .grpc.examples.echo.EchoRequest ) returns ( 
  	stream .grpc.examples.echo.EchoResponse );

  // ClientStreamingEcho is client side streaming.
  rpc ClientStreamingEcho ( 
  	stream .grpc.examples.echo.EchoRequest ) returns ( 
  	.grpc.examples.echo.EchoResponse );

  // ServerStreamingEcho is server side streaming.
  rpc ServerStreamingEcho ( 
  	.grpc.examples.echo.EchoRequest ) returns ( 
  	stream .grpc.examples.echo.EchoResponse );

  // UnaryEcho is unary echo.
  rpc UnaryEcho ( 
  	.grpc.examples.echo.EchoRequest ) returns ( 
  	.grpc.examples.echo.EchoResponse );
}

相较使用服务端的反射服务,加载文件的方式会输出本身的注释信息。

当然除了输出服务的描述信息外也可以输出 message 描述信息:

% grpcurl -plaintext 127.0.0.1:50051 describe grpc.examples.echo.EchoRequest
grpc.examples.echo.EchoRequest is a message:
message EchoRequest {
  string message = 1;
}
% grpcurl -plaintext 127.0.0.1:50051 describe grpc.examples.echo.EchoResponse
grpc.examples.echo.EchoResponse is a message:
message EchoResponse {
  string message = 1;
}

案例4 与 gRPC 服务端进行交互

服务端部分交互代码如下:

type ecServer struct { // Echo 服务的实现
	ecpb.UnimplementedEchoServer
}

func (s *ecServer) UnaryEcho(
	ctx context.Context, req *ecpb.EchoRequest) (*ecpb.EchoResponse, 
	error) {
	return &ecpb.EchoResponse{Message: req.Message}, nil
}

通过 -d 参数发送 JSON 数据

 % grpcurl -plaintext -d '{"message":"hi"}' 127.0.0.1:50051 grpc.examples.echo.Echo.UnaryEcho
{
  "message": "hi"
}

其他


tangzixiang