This post may be helpful for you if you are building gRPC services and want a convenient way to test your service using a command line tool. Similar to using cURL when testing HTTP(s) services, I wanted an easy way to test the gRPC services that I’m building.
Originally, I had originally planned to whip together a tiny C++ program that sends protobuf messages to my MapReduce service that I’m building for advanced operating systems course. Fortunately, a testing tool already exists: grpc_cli. Even better is that the tool ships with the grpc source code.
So follow along if you want to install the grpc command line tool, enable server reflection, and execute a few examples.
Note: This post assumes that you are programming in C++ and your operating system is Ubuntu
Install grpc_cli
Follow the steps below if you are running on Ubuntu. If you are running gRPC on your mac, then you’ll want to substitute the apt-get command with brew install, as described in the grpc command line documentation.
- Clone the grpc repository
[code lang=”bash”]git clone git@github.com:grpc/grpc.git[/code]
- Add submodules
[code lang=”bash”]$ git submodule update –init[/code]
- Install libflags-dev
[code lang=”bash”]$ sudo apt-get install libgflags-dev[/code]
- Compile grpc
[code lang=”bash”]$ mkdir -p cmake/build
$ cd cmake/build
$ cmake -DgRPC_BUILD_TESTS=ON ../..
$ make grpc_cli
[/code]
Enable Reflection for your service
In your grpc service code, before you bind and listen, you’ll need to enable reflection. Although not entirely necessary for interacting with your service, not having reflection enabled means you cannot use many of the grpc_cli commands like list.
[code lang=”bash”]
grpc::reflection::InitProtoReflectionServerBuilderPlugin();
grpc::ServerBuilder builder;
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
builder.RegisterService(&service);
…
[/code]
Add grpc++_reflection library
Make sure that you are adding grpc++ library when building your project. If you are a student in advanced operating systems, you’ll need to update GeneratedProtos.cmake
and link the gRPC::grpc++_reflection
library as follows:
[code lang=”bash”]
% git diff
diff –git a/src/GenerateProtos.cmake b/src/GenerateProtos.cmake
index c6a80bc..cce2d51 100644
— a/src/GenerateProtos.cmake
+++ b/src/GenerateProtos.cmake
@@ -75,5 +75,5 @@ add_custom_command(
)
add_library(p4protolib ${ProtoHeaders} ${ProtoSources})
-target_link_libraries(p4protolib PUBLIC protobuf::libprotobuf gRPC::grpc++)
+target_link_libraries(p4protolib PUBLIC protobuf::libprotobuf gRPC::grpc++ gRPC::grpc++_reflection)
target_include_directories(p4protolib PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR})
[/code]
Using grpc_cli
I’d encourage you to explore the grpc_cli by checking out the official user guide. However, for the purpose of this post, I want to show you how to list your service as well as how to invoke the “MapReduce” service.
Examples
Start your gRPC service
In the example below, I’m staring my worker process that listens on localhost:50051. Here’s a snippet of my very bare service:
[code lang=”proto3″]
service MapReduce {
rpc map(MapRequest) returns (MapResponse) {}
rpc reduce(ReduceRequest) returns (ReduceResponse) {}
[/code]
Starting the service
[code lang=”bash”]
$ ./mr_worker localhost:50051
Listening on ip address: localhost
Listening on port: 50051
Server listening on localhost:50051
[/code]
List the services
After starting my service (that has reflection enabled), the service shows up when I execute the list command:
[code lang=”bash”]
$ ./grpc_cli ls localhost:50051
masterworker.MapReduce
grpc.reflection.v1alpha.ServerReflection
grpc.health.v1.Health
[/code]
Invoking “MapReduce”
[code lang=”bash”]
$ ./grpc_cli call localhost:50051 masterworker.MapReduce.map "shard_data: ‘123’"
connecting to localhost:50051
Rpc succeeded with OK status
[/code]
Passing in multiple fields
[code lang=”bash”]
$ ./grpc_cli call localhost:50051 masterworker.MapReduce.reduce "filename: ‘123’ worker_hostname: ‘localhost’ worker_port: 50051"
connecting to localhost:50051
Rpc succeeded with OK status
[/code]
References
- https://grpc.github.io/grpc/cpp/md_doc_server_reflection_tutorial.html
- https://github.com/grpc/grpc/blob/master/doc/command_line_tool.md
- https://stackoverflow.com/questions/61641174/unable-to-link-the-grpc-libraries-in-windows