What is gRPC and Building a gRPC service on .Net Core

Caner Tosuner
hepsiburadatech
Published in
8 min readJun 2, 2020

In this article we are going to talk about what gRPC is in general terms, how it came about, and how we can implement it on a sample .net core application.

gRPC is a remote-procedure-call (RPC) library developed by google as an internal project for scalability problems and then it was introduced as an open source library in 2015. It uses the HTTP/2 protocol for transport and offers an infrastructure that can serialize/deserialize binary-message exchange using a binary serialization protocol named Protocol Buffers (protobuf) and first released by google. Protobuf is basically a binary serialization protocol and stands out for its high performance with low CPU usage. Especially with the widespread use of IoT applications in recent years, gRPC is considered as one of the first options for inter-device communication, since there is much smaller technology between devices.

gRPC is also used in Microservice architectures. When you design a structure on the Microservice architecture and consider that you have quite a lot of services, there will always be communication between these services or between service-to-3rd party applications. Especially Restful services, which are mostly suitable for structures that are mostly consumed by an external client, and RESTful services are considered to be not actually the most ideal option for internal service-to-service communication since they are based on more human-optimized text-based messaging. Instead of using gRPC for service-to-service internal communication, which has support in almost all software languages, has recently become a highly recommended and preferred option.

When you think about DDD principle, it tells you to separate the business capabilities into bounded contexts and they should not have any dependencies in terms of code-sharing. In other words; if you have bounded-contexts in the same solution, there will always be a risk of dependency because it is easy to reference them each other to access and most probably you will start not caring about it day by day. Instead of this approach, if you use gRPC programming to communicate these bounded contexts you can easily share a .proto file as a clear contract and this will make your architecture more well-defined.

If we look at the concepts and client-server communication types that gRPC supports;

Unary RPC

The communication type that the client sends a single request and receives a single response in return.

Server streaming RPC

The type of communication in which the server receives a request from the client and returns a response stream.

Client streaming RPC

The opposite of server streaming, the client sends multiple messages and after the server processes these messages, a single response is returned to the client.

Bidirectional streaming RPC

The type of communication that both client and server can do message streaming.

The client or server can cancel the RPC at any time. Deadlines / Timeouts allows gRPC clients to set a timeout time to query whether any RPC is a timeout on their server.

Sample Project

If we examine on a sample case; Let’s imagine that we have developed an e-commerce site and the customer wants to request a refund for a product they purchased. By defining gRPC Interface Definition Contracts, communication between client-server is completed through http2 protocol. Afterwards, notification is sent to NotifyCustomerClient and a notification sms or e-mail is sent to the customer.

Creating gRPC Service

Let’s create a sample project by using asp.net core 3.1 version over the refund example mentioned above. First, we need to create a project in VS. using the gRPC Service template and named RefundService.

If we look at the solution after creating our project; when you create a new gRPC project, it comes with a sample gRPC implementation called GreeterService by default.

As it turns out, the project actually consists of a GreeterService class and the greet.proto contract file defined for this class. In other words, GreeterBase and GreeterService classes that are generated according to the definitions in the greet. The proto file is included in the project.

Adding gRPC to Services

If we look at Startup.cs, you need to add gRPC to application services in order to use gRPC in your project, and then we must define the service-endpoint mapping in the Configure method.

Creating refund.proto file

Let’s start defining our methods inside the refund.proto file. There will be 2 methods in RefundService which are Refund() and NotifyCustomer() methods. While the Refund method is serving in the Unary RPC type, the NotifyCustomer method will serve in the Server Streaming RPC type.

RefundService Implementation

If we look at the RefundService class; There will be a service class consisting of code blocks with the implementation of the 2 methods we have described above. While the Refund method works for the customer’s refund requests, the NotifyCustomer method will act as the responsible for sending notifications to the customer regarding the refund process.

Our gRPC service application is now ready to host and all we have to do is run the application. After running the project, you will see info-logs about the service in the console as follows.

The server will start listening the port 5001 using HTTPS (and 5000 using HTTP) according to the default settings. Our RefundService application is now ready to consume and we can start using Refund and NotifyCustomer methods by defining new clients.

Now, we will create a client project for the Refund method of the RefundService application and observe how these two applications communicate each other using the Unary RPC method.

Unary RPC; It is one of the types of communication between the server and client, where the client sends a single request and receives a response.

Creating Unary gRPC Refund Client

Let’s start creating the client that will call the Refund method in RefundService. For this, let’s create a ConsoleApp called RefundClient in the same solution and add Grpc.Tools, Grpc.Net.Client, Google.Protobuf libraries to the project references via nuget. Then, after creating the folder named Protos in the client project, copy the refund.proto file from RefundService project to RefundClient project. Since this client will only call the Refund method, let’s delete notify related definitions from this new .proto file. After copying, we need to change the GrpcServices value to Client, where the refund.proto file is referenced in the client project csproj file. The values that can be set are; Both, Client, Default, None, Server.

RefundClient project will look like this.

Let’s write the code-blocks that will initialize a channel and start calling Refund method.

Firstly, by setting url information, we define a channel and initialize RefundServiceClient while passing this channel information as a parameter and establish conn. Then call the Refund method and send the refund request to the service.

We have completed both Service and Client development for the refund process. All we have to do is run both applications and make sure that they are working as expected.

As we have seen, both the refundClient and the refundService applications have completed the refund process for orderId 43243546 and we have seen that they displayed the relevant logs in their consoles.

Creating Server Streaming RPC NotifyCustomer Client

The next step is to create NotifyCustomer Client, which will provide Server Streaming RPC communication type and we will use it to notify the customer after the Refund request.

Let’s create a client application for the NotifyCustomer method defined in RefundService. After the refund process is completed, we expect to see the message(any email, or sms) sent to this client. To do this, let’s create a consoleApp called NotifyCustomerClient in the solution and add required nuget libraries to the references, just like we did in the previous application.

All the development process is finished and if we check it step by step;

  1. RefundClient request for a refund
  2. RefundService process this request and stream for NotifyCustomerClient
  3. NotifyCustomerClient consumes messages from RefundService

After running all the applications in solution, we can easily see all process by looking at the console-logs of the applications.

RefundClinet sends a refund request to RefundService in Unary RPC type, then the service application processed it and returned a refund message to the refundClient. NotifyCustomerClient application started consuming the Notify method served in RefundService by using Server Streaming RPC type. If there exists any processed refund requests RefundService will start sending them to NotifyCustomerClient.

If we want to communicate two microservices, assume that you have a service named FinancialService and you have to make a service-to-service call after the refund process. All you need to do is, define the .proto file of the FinancialService in RefundService project and make a simple call for it’s method, for example CancelPayment(). To do this we can make use of Grpc.Net.ClientFactory nuget library and implement it in ConfigureServices method as below.

gRPC doesn’t have all the pros of REST but there are many companies using it as a strategy because of the power of a millisecond.

gRPC Pros; high performance, contract-based api development, faster serialization with small payload, bi-directional streaming and machine-readable (it’s binary), considered as the best choise for device-to-device and device-to-cloud communicaton for embedded systems etc.

gRPC Cons; Limited browser support(impossible to directly call a gRPC service from a browser), not human readable, lots of people have experiences in REST based development but less for gRPC development etc.

It’s clear that gRPC is faster and we can conclude that gRPC is overall winner in terms of speed, but besides the speed, gRPC and REST both have their own advantages. It is a really critical decision to make a choice between them.

In this article, we have seen how we can design server-client structures using gRPC, which has been in our lives for a while but has increased its new popularity. Sending a request and receiving a response in less than 30 Milliseconds is fast but we are as programmers are still trying to decrease this duration because we know that milliseconds do matter on a large scale system.

You can find much more information here.

--

--