Author | Mohamad Lawand
Translated by | Zhang Weibin
Planning | Ding Xiaoyun
Essentially, an API is a protocol between the server and the client that specifies how the server provides specific data based on the client's request.

When building APIs, we think of different technologies. Depending on the requirements, the technology we choose to develop the API will change accordingly. In this day and age, there are two main techniques for creating APIs:
gRPC
REST
Both technologies use HTTP as the transport mechanism. Although the same underlying transport mechanism is used, their implementations are completely different.
Let's compare the two technologies before we dive into gRPC.
REST is a set of architectural constraints, not protocols or standards. API developers can implement REST in a variety of ways.
In order for an API to be considered RESTful, we need to follow some constraints:
Client-side - server-side architecture: all requests must use HTTP as the transport mechanism;
Stateless: The API should be stateless, which means that the server should not store any state about the client session on the server side. Every request from the client to the server must contain all the necessary information to understand the request. The server cannot use any context stored on the server side.
Cacheable: All data flowing between clients and servers must be cacheable, which means that they can be stored for subsequent retrieval and use.
Unified Interface: There must be an interface between the client and the server so that information can be transmitted in standard form.
Hierarchical system: All servers involved between the client's request and the server-side response must be organized according to their responsibilities, and the organization cannot affect the request or response.
gRPC is built on the solid foundation of the RPC (Remote Procedure Call) protocol, and it has also entered the realm of APIs. gRPC is a free, open-source framework developed by Google that uses HTTP/2 for API communication, hiding http implementations for API designers.
gRPC has many characteristics, so it makes it a foundational module for the next generation of web applications, both in microservices and in web/mobile API communication:
Interoperability: Regardless of the current HTTP version and how the infrastructure changes (e.g., from HTTP 2 to HTTP 3), the protocol must be able to adapt and change.
Layered architecture: The core surface of the technology stack must be able to evolve and upgrade independently without breaking any application that uses it.
Agnostic: Different services may require different message types and encodings, such as Protobuf (Protocol buffer), JSON, XML, etc. gRPC supports all of these formats and is capable of compressing loads by utilizing pluggable compression mechanisms.
Streaming: gRPC allows large data sets to be streamed from the server to the client and vice versa.
Pluggable: gRPC supports plugging in different features and services as needed to meet our needs, such as health checks, failback, and load balancing. The framework implementation provides extensibility points that allow us to plug in these features.
Similar to Docker and Kubernetes, gRPC is part of the Cloud Native Foundation (CNCF).
In short, the benefits of gRPC include:
Modern and fast
open source
Take advantage of HTTP/2
Language neutral
Easy to add certifications, logs
In order to use gRPC:
We need to use Protobuf (Protocol Buffer) to define messages and services
The gRPC code is automatically generated, and we need to provide a specific implementation.
Whether on the server side or on the client side, files can support 12 different languages.
By default, gRPC uses Google's open source Protocol Buffers mechanism for serializing structured data:
It is language neutral
Ability to generate code for any modern programming language
Data transfer is binary and efficient
Highly scalable
Allows us to send large amounts of data
Allows us to extend and evolve the API
Case Study:
In today's technology trends, the more modern approach is to build microservices. In this example, we learn about the process of building an air ticketing system:
The image above shows an air ticketing system based on microservices. Here, there are several key points related to this type of architecture that we need to pay attention to:
Microservices are often built in different languages. Then we can say that the booking management service can be based on . NET is built, payment processing can be Java-based, and passenger information can be .js using Node.
Each service has a different business function.
Suppose we now have microservices written in different languages, and they have to communicate with each other. When these microservices want to exchange information, they need to agree on something, such as:
AN API for exchanging data
data format
Incorrect format
Access speed limits
REST is the most popular scenario for building APIs. However, this decision depends on a number of architectural considerations related to our implementation:
The type of design data model;
What the endpoint will look like;
How errors should be handled;
How many calls a client can make;
How authorization is achieved.
With these factors in mind, let's take a look at the differences between gRPC and REST:
Contract-first API development: Contracts (services and messages) are defined in files and are at the heart of gRPC. This is a language-neutral way of defining the API. These files can then be used by other programming languages to generate code, such as strongly typed clients and message classes.
Content is binary: HTTP/2 and Protobuf are binary protocols, and content is designed for computers and high performance.
The design of gRPC hides the complexity of remote operation. By using the gRPC library and associated code generation, we don't need to care about issues like routing, header information, and serialization. When we need to call a method on the client side, we only need to call the corresponding method.
gRPC supports two-way asynchronous streaming: after a gRPC call establishes a stream, both the client and the server can send asynchronous streams to each other at any time. Server and client flows (in which case only one of the responses or requests is a stream) are also supported.
gRPC is designed for high performance and productivity in distributed applications.
REST API
Content-first API development (URLs, HTTP methods, JSON): focus on readability and formatting.
The content is text-based (HTTP 1.1 and JSON), so it's human-readable. As a result, they are great for debugging, but not performance-friendly.
More emphasis is placed on HTTP. We need to think about low-level issues, which is a good thing because we have a lot of control over HTTP requests.
For CRUD.
Broadest audience: Http/1.1 and JSON are available on every computer for easy access.
Based on these comparisons, we can see that both approaches have their advantages. However, we can see that gRPC provides a powerful set of features for microservices-based scenarios.
Create a server-client app using gRPC
Before we start coding, we install the following software on our own computer:
.NET Core 5 SDK
Visual Studio Code
After the software installation is complete, we need to create the project structure (in this article we will use the dotnet command directly in the terminal / command line):
We also need to configure the SSL trust:
Next, we open this new project in VS Code to see what has been created. As we can see, we automatically have the following:
Protos folder
Services folder
In the Protos folder, we have a green.proto file. As we mentioned earlier, .proto can define APIs in a language-neutral way.
From this file, we can see that it contains a Greyter service and a SayHello method. We can think of the Greener service as a controller and the SayHello method as an action. The contents of the proto file are as follows:
The SayHello method receives a HelloRequest (which is a message) and returns a HelloReply (which is also a message).
In the GreyterService file, we can see that there is a GreenerService class, which inherits from Greyter.GreeterBase, which is automatically generated from the .proto file.
In the SayHello method, we receive a request (HelloRequest) and return a response (HelloReply). They are also automatically generated for us by .proto files.
Code automatic generation is defined as the files we need to generate based on the .proto file. gRPC does all the heavy lifting for us in code generation, routing, and serialization. All we need to do is implement the base class and override the implementation of the method.
Next, we try to run the gRPC service:
As you can see from the results of the auto-generated endpoints, we can't use gRPC like we did with a web browser as a REST client. In this case, we need to create a gRPC client to communicate with the service. For our client, gRPC also needs a .proto file because it is a contract-first RPC framework. Currently, our web browser knows nothing about the client (we don't have a .proto file), so it doesn't know how to handle the request.
We create a custom .proto file named consumers.proto. This file must be created in the Protos folder and its contents are as follows:
After saving the above file, we need to add it to the .csproj file:
Now we need to build the app:
The next step is to add our ConsumerService class to the Services folder and update its contents as follows:
Now we need to update the Startup .cs class to inform our application that our newly created service has a new endpoint. To achieve this, the Configure method (located in the app. UserEndpoints) inside, we need to add the following code:
Notes under MacOS:
Because MacOS does not support HTTP/2 on top of TLS, we need to update the Program .cs file in the following scenario:
The next step is to create our client app:
Now we need to add the necessary packages to the client console app to make it gRPC-aware. This can be achieved in the GrpcGreeterClient class:
Because we need the client to have the same contract as the server, we need to add the .proto file created in the previous steps to the client app. To achieve this:
1. First, we need to add a folder named Protos to the client project.
2. We need to copy the contents of the Protos folder in the gRPC greeter service to the gRPC client project, i.e
3. After pasting the file, we need to update the namespace to be the same as the client app:
4. We need to update the GrpcGreeterClient.csproj file so that it knows about our newly added .proto file:
This Protobuf element is a way for code to automatically generate attributes to understand .proto files. With the above changes, we indicate here that we want the client to use our newly added .proto file.
We need to build the client and make sure everything builds successfully:
Now, let's add some code to the console app to make it easier to invoke the server side. In the Program .cs file, we need to make the following changes:
Now let's add stream processing capabilities to the app.
Let's go back to the consumers.proto file and add a stream method to the Consumer service:
As we can see, in the return, we added the stream keyword, which means that we are adding a stream consisting of "multiple" replies.
At the same time, we also need to add an empty message
To implement this method, we need to go to the Services folder and add the following code to the ConsumerService class:
Now we need to copy the changes to the server-side customers.proto file to the client's consumers.proto file:
Now we need to build the app again:
Our next step is to update the Program .cs file in GrpcClientApp to handle the new streaming method:
Now, let's go back to The GrpcGreeter and update the greet.proto file to add a stream method to it:
As you can see, in the return we added the keyword stream, which means we're adding a stream consisting of "multiple" replies. To implement this method, we need to go to the Services folder and add the following in GreeterService:
Now we need to copy the changes to the green.proto file from the server side to the client side and build it. In the client application's green.proto file, we add the following line of code:
Make sure that after you save the .proto file, build your app.
Now we can open the Program .cs and use the new method:
This example illustrates how we do it. Client-server applications that implement gRPC in NET 5.
Summary
We can see the power of gRPC in building applications, but it is not easy to exert this power because building gRPC services requires more build time and coordination between client and server. With REST, we barely need any setup to start consuming endpoints.
gRPC doesn't necessarily replace REST, as both technologies have specific use cases. Choose the right technology for your project based on your business scenario and needs.
About the Author:
Mohamad Lawand is a committed, forward-thinking technology architect with more than 13 years of experience working in a wide range of industries, from financial institutions to government entities. He is proactive and adaptable, excelling at SaaS and blockchain technology across multiple platforms. Mohamad also owns a Youtube channel where he shares his knowledge.
https://www.infoq.com/articles/getting-started-grpc-dotnet/