gRPC Server Reflection provides information about publicly-accessible gRPC services on a server, and assists clients at runtime to construct RPC requests and responses without precompiled service information. It is used by gRPC CLI, which can be used to introspect server protos and send/receive test RPCs.
C++ Server Reflection is an add-on library, libgrpc++_reflection
. To enable C++
server reflection, you can link this library to your server binary.
Some platforms (e.g. Ubuntu 11.10 onwards) only link in libraries that directly
contain symbols used by the application. On these platforms, LD flag
--no-as-needed
is needed for dynamic linking and --whole-archive
is
needed for static linking.
This Makefile demonstrates enabling c++ server reflection on Linux and MacOS.
After enabling Server Reflection in a server application, you can use gRPC CLI to test its services.
Instructions on how to use gRPC CLI can be found at
command_line_tool.md, or using grpc_cli help
command.
Here we use examples/cpp/helloworld
as an example to show the use of gRPC
Server Reflection and gRPC CLI. First, we need to build gRPC CLI and setup an
example server with Server Reflection enabled.
-
Setup an example server
Server Reflection has already been enabled in the Makefile of the helloworld example. We can simply make it and run the greeter_server.
$ make -C examples/cpp/helloworld $ examples/cpp/helloworld/greeter_server &
-
Build gRPC CLI
make grpc_cli cd bins/opt
gRPC CLI binary
grpc_cli
can be found atbins/opt/
folder. This tool is still new and does not have amake install
target yet.
grpc_cli ls
command lists services and methods exposed at a given port
-
List all the services exposed at a given port
$ grpc_cli ls localhost:50051
output:
helloworld.Greeter grpc.reflection.v1alpha.ServerReflection
-
List one service with details
grpc_cli ls
command inspects a service given its full name (in the format of <package>.<service>). It can print information with a long listing format when-l
flag is set. This flag can be used to get more details about a service.$ grpc_cli ls localhost:50051 helloworld.Greeter -l
output:
filename: helloworld.proto package: helloworld; service Greeter { rpc SayHello(helloworld.HelloRequest) returns (helloworld.HelloReply) {} }
-
List one method with details
grpc_cli ls
command also inspects a method given its full name (in the format of <package>.<service>.<method>).$ grpc_cli ls localhost:50051 helloworld.Greeter.SayHello -l
output:
rpc SayHello(helloworld.HelloRequest) returns (helloworld.HelloReply) {}
We can usegrpc_cli type
command to inspect request/response types given the
full name of the type (in the format of <package>.<type>).
-
Get information about the request type
$ grpc_cli type localhost:50051 helloworld.HelloRequest
output:
message HelloRequest { optional string name = 1; }
We can send RPCs to a server and get responses using grpc_cli call
command.
-
Call a unary method
$ grpc_cli call localhost:50051 SayHello "name: 'gRPC CLI'"
output:
message: "Hello gRPC CLI"
Server Reflection can be used by clients to get information about gRPC services at runtime. We've provided a descriptor database called grpc::ProtoReflectionDescriptorDatabase which implements the google::protobuf::DescriptorDatabase interface. It manages the communication between clients and reflection services and the storage of received information. Clients can use it as using a local descriptor database.
-
To use Server Reflection with grpc::ProtoReflectionDescriptorDatabase, first initialize an instance with a grpc::Channel.
std::shared_ptr<grpc::Channel> channel = grpc::CreateChannel(server_address, server_cred); grpc::ProtoReflectionDescriptorDatabase reflection_db(channel);
-
Then use this instance to feed a google::protobuf::DescriptorPool.
google::protobuf::DescriptorPool desc_pool(&reflection_db);
-
Example usage of this descriptor pool
-
Get Service/method descriptors.
const google::protobuf::ServiceDescriptor* service_desc = desc_pool->FindServiceByName("helloworld.Greeter"); const google::protobuf::MethodDescriptor* method_desc = desc_pool->FindMethodByName("helloworld.Greeter.SayHello");
-
Get message type descriptors and create messages dynamically.
const google::protobuf::Descriptor* request_desc = desc_pool->FindMessageTypeByName("helloworld.HelloRequest"); google::protobuf::DynamicMessageFactory dmf; google::protobuf::Message* request = dmf.GetPrototype(request_desc)->New();
-