In this example, we will write a client side and a server side for a simple GreeterService from greeter.proto (see the schema below). Its single SayHello method accepts a name string and replies with a corresponding greeting string.
Installation
We generate and link to a CMake library from our .proto schema:
// Initiate the RPC. No actual actions have been taken thus far besides
// preparing to send the request.
auto stream = client_.SayHello(request, std::move(context));
// Complete the unary RPC by sending the request and receiving the response.
// The client should call `Finish` (in case of single response) or `Read`
// until `false` (in case of response stream), otherwise the RPC will be
// cancelled.
api::GreetingResponse response = stream.Finish();
return std::move(*response.mutable_greeting());
}
Fill in the static config entries for the client side:
# Creates gRPC clientsgrpc-client-factory:# The TaskProcessor for blocking connection initiationtask-processor:grpc-blocking-task-processor# Optional channel parameters for gRPC Core# https://grpc.github.io/grpc/core/group__grpc__arg__keys.htmlchannel-args: {}
# Our wrapper around the generated client for GreeterServicegreeter-client:# The service endpoint (URI). We talk to our own service,# which is kind of pointless, but works for an exampleendpoint:'[::1]:8091'
task_processors:grpc-blocking-task-processor:# For blocking gRPC channel creationthread_name:grpc-workerworker_threads:2
The server side
Implement the generated api::GreeterServiceBase. As a convenience, a derived api::GreeterServiceBase::Component class is provided for easy integration with the component system.
// Complete the RPC by sending the response. The service should complete
// each request by calling `Finish` or `FinishWithError`, otherwise the
// client will receive an Internal Error (500) response.
call.Finish(response);
}
Fill in the static config entries for the server side:
# Common configuration for gRPC servergrpc-server:# The single listening port for incoming RPCsport:8091# Our GreeterService implementationgreeter-service:task-processor:main-task-processorgreeting-prefix:Hellomiddlewares: []
int main()
Finally, we register our components and start the server.
To build the sample, execute the following build steps at the userver root directory:
mkdir build_release
cd build_release
cmake -DCMAKE_BUILD_TYPE=Release ..
make userver-samples-grpc_service
The sample could be started by running make start-userver-samples-grpc_service. The command would invoke testsuite start target that sets proper paths in the configuration files and starts the service.
To start the service manually run ./samples/grpc_service/userver-samples-grpc_service -c </path/to/static_config.yaml> (do not forget to prepare the configuration files!).
The service is available locally at port 8091 (as per our static_config.yaml).
Functional testing
To implement Functional tests for the service some preparational steps should be done.