Introduction to gRPC

Learn about the components of gRPC and the reason behind its popularity.

gRPC is an open-source remote procedure calls (RPC) framework designed for high performance. While RPC in gRPC stands for “remote procedure calls,” the lowercase letter “g” doesn't stand for anything, though there are common misconceptions that it either stands for “general” or “Google.” The framework was initially created by Google, where it was used as one of its internal technologies. However, in 2016, it was publicly released as an open-source project. It has been regularly updated since.

The gRPC logo
The gRPC logo

Since its public release, gRPC has become really popular among developers, and gRPC libraries have been made available for the majority of popular programming languages and frameworks. Since the release of .NET Core 3.0, gRPC has been available on ASP.NET Core as a first-class citizen, meaning that the libraries and all supporting tools required to integrate it into ASP.NET Core applications are available as modules of the ASP.NET Core framework itself. We still need to download NuGet packages to enable gRPC. However, all of the NuGet packages we need have been developed by the same team that developed ASP.NET Core itself. This is what enables its seamless integration into the platform.

What makes gRPC so popular

The main advantage of gRPC is that it's been specifically designed for high-performance communication between services over HTTP. However, the benefits of gRPC don't stop there. The key advantages of the framework can be summarized as follows:

  • It's high performing due to utilization of the latest HTTP/2 and HTTP/3 features.

  • Its message serialization protocol, Protobuf, is designed to keep the message size as small as possible, which helps save bandwidth.

  • Multiple message transfer modes, and not just the standard request-response model, are available.

  • It's easy to integrate into the application code with built-in code generators.

  • It's easy to write implementations of gRPC services due to its intuitive and strongly-typed schema.

  • It's easy to find code samples for the problems we're trying to solve because many code samples are available online.

  • It's one of the best mechanisms for direct instant communication between microservices.

  • Since gRPC libraries are available for most of the popular programming languages, the client and server can be written in different languages.

  • It's designed for easy API versioning.

  • It has a relatively gentle learning curve.

What gRPC consists of

gRPC can be thought of as a wrapper protocol. It relies on other protocols to transfer messages, such as HTTP/2 and HTTP/3. It depends on the latest features of these protocols, such as multiplexing, to allow it to deliver multiple messages over the same connection in parallel. However, as gRPC is a whole framework rather than just a protocol, it also removes the need to manually write requests and responses over HTTP/2 and HTTP/3, including its complex headers and binary payload. It enables developers to write code that's as intuitive as the process of calling methods in the classes of the same application.

To enable all of this, gRPC implements the following components:

Protobuf serialization

Protobuf is a message serialization protocol that gRPC uses. This is usually the first thing developers will need to deal with when writing gRPC client and server implementation. A noteworthy exception is the code-first gRPC, which we'll cover later.

Even though the messages are serialized for small size and efficient transmission over the network, the message definition itself is intuitive. Here's an example of a Protobuf file. Any experienced developer should be able to get a rough idea of what's going on, even if they haven't worked with gRPC before:

syntax = "proto3";
option csharp_namespace = "BasicGrpcService";
package basic_grpc_service;
service Chatbot {
rpc SendMessage (ChatRequest) returns (ChatReply);
}
message ChatRequest {
string name = 1;
string message = 2;
}
message ChatReply {
string message = 1;
}

The example above has a service called Chatbot. This service has a method or function called SendMessage, which can be seen on line 8. This method accepts the ChatRequest message as its input and returns the ChatReply message as its output. These messages are defined on lines 11 and 16 respectively.

We'll cover Protobuf in more detail later. However, even now we can appreciate how intuitive the message schema is. It's not too verbose, unlike the infamous XML. At the same time, it's descriptive enough that it's easy to determine what's going on.

Code generator

Any language-specific implementation of gRPC will come with tools that can read Protobuf definitions and translate them into objects and modules specific to the language. These will be stub objects that we can call directly from our own code. In the case of C#, if we look at the above example, the tools will translate the schema into three classes: Chatbot, ChatRequest, and ChatReply.

Message generator

Once our stub objects have been generated, we won't have to worry about converting data from our code into gRPC messages. The underlying framework will do it for us. All we'll have to do is specify the correct gRPC server URL and call an appropriate method on an appropriate auto-generated object. So, to us, the process of calling a remote procedure will not be in any way different from just calling a method inside one of our own classes. This is because the underlying framework will take care of it for us.

Once a method on a stub object is called, an appropriate request will be constructed. Our data will be serialized into a binary format and added to the request as its payload. The request will be sent to the remote location that we've specified in the URL. Then, the response will be delivered in the same manner.