Published:

Jarle Aase

Overview

bookmark 4 min read

What is gRPC anyway?

I'm not attempting a general introduction to gRPC. See the links at the end of this page if you need to catch up ;)

So, what is gRPC? In my opinion, it's an internal project at Google that is released to the public as open source, but without proper documentation for advanced use. It's relatively simple to create a Proof of Concept project in C++ or Python (the two languages I have used with gRPC recently) - but when you wander into the "Bay of Asynchronous Requests", it's not in any way obvious what to do. Lets be clear about this: Using gRPC with C++ for production grade code is hard. It takes time to understand how Googles engineers envision that the generated server interfaces and client side stubs will be used. It takes time to set up a project with CMake to correctly generate the C++ files. It takes considerable efforts if you need to automatically build the protobuf and gRPC libraries and utilities yourself. I'll not touch the latter in this blog-series, but use the libraries and utilities that is available from my Linux distributions (I use Debian and Kubuntu).

From a C++ perspective, the async API's provide a solid foundation to implement formidable servers to handle gRPC clients. Google has prioritized high performance over type safety and C++ best practices. That's an understandable approach. I assume that they use gRPC in their massive server infrastructure. Electric power is expensive, and instructions saved in very hot paths in their server applications will add up to significant savings. Using the async interfaces is however hard. This is especially true for the legacy async interface that most people are probably still using. Each RPC (Remote Procedure Call) require lots of boilerplate code. Again, this makes sense for Google who has lots of programmers, and probably a large number of experts on gRPC. I would not be surprised to learn about internal tools that can generate most, if not all of the boilerplate code.

What are the cons and pros with the legacy async interface?

Positives

Negatives

What are the cons and pros with the newer async callback interface?

Positives

Negatives

Tools and requirements

I will be using CMake and C++ 20. I test my code with g++ 12 and 13, and clang 15. In addition to protobuf and grpc, I will use a recent version of the boost libraries. For logging, I use a header-only log library, logfault, that is handled automatically by CMake.

CMake and gRPC

CMake can deal with the code-generation from .proto files required to use gRPC in your project. I have found it useful to create a static library for the protobuf and gRPC details, and just add that to the dependencies of my other libraries and/or executables.

Example:

 1project(proto LANGUAGES CXX)
 2
 3INCLUDE(FindProtobuf)
 4FIND_PACKAGE(Protobuf REQUIRED)
 5find_package(gRPC CONFIG REQUIRED)
 6set(GRPC_LIB gRPC::grpc gRPC::grpc++)
 7
 8file(GLOB PROTO_FILES "${PROJECT_SOURCE_DIR}/*.proto")
 9message("   using PROTO_FILES: ${PROTO_FILES}")
10
11add_library(${PROJECT_NAME} STATIC ${PROTO_FILES})
12target_link_libraries(${PROJECT_NAME}
13    PUBLIC
14        $<BUILD_INTERFACE:protobuf::libprotobuf>
15        $<BUILD_INTERFACE:${GRPC_LIB}>
16)
17
18target_include_directories(proto PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
19get_target_property(grpc_cpp_plugin_location gRPC::grpc_cpp_plugin LOCATION)
20protobuf_generate(TARGET ${PROJECT_NAME} LANGUAGE cpp)
21protobuf_generate(TARGET ${PROJECT_NAME} LANGUAGE grpc GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc PLUGIN "protoc-gen-grpc=${grpc_cpp_plugin_location}")

The latest version of this example is here:

Then, when you make something that use the gRPC stuff, just mention proto in that projects CMakeLists.txt:

1add_dependencies(${PROJECT_NAME}
2    proto
3    ...
4    )

gRPC general information

Some things to read, if you are unfamiliar with gRPC.

Official info and tutorials from the gRPC team:

Other relevant links: