What is RPC (Remote Procedure Call): gRPC vs REST
RPC, which stands for Remote Procedure Call, is a communication interface or protocol that enables a program running on one computer to execute code on a remote computer or server. It allows clients to invoke procedures or functions on a remote server seamlessly, abstracting the complexities of network communication. RPC consists of two APIs: one for defining RPC functions in a transport-independent way and another for implementing RPC transports. The RPC API contains functions for modifying and sending a reply, with support of parameters and returning multiple values as results.
RPC works by making a function call across a network as if it were a local function call (similar to WCF). The client initiates the RPC request, specifying the method or procedure to be executed, along with any necessary parameters via a specific URL. The request is then transmitted over the network to the remote server, which receives the request and executes the specified method. When making a Remote Procedure Call, the calling environment is suspended, procedure parameters are transferred across the network to the environment where the procedure is to execute, and the procedure is executed there. Once the execution is done, the server then sends the result of the execution back to the client. Both the client and server do not execute at the same time, it is the thread that jumps from client to server and back.
RPC typically relies on a middleware layer or library that handles the network communication and marshaling/unmarshalling of data between the client and the server. It provides a higher-level abstraction that simplifies the development of distributed systems by hiding the details of network communication. Asp.net Development company can be anything and multiple clients can connect with different languages. The client doesn’t need to be a web application. It can be anything like a Windows application, Command Line Application, or any Web Application.
History of gRPC:
Google created Stubby, which has a single general-purpose RPC infrastructure to link numerous microservices that operate within and across its data centers. In March 2015, Google decided to develop the next iteration of Stubby and release it as an open-source project. This led to the creation of gRPC.
gRPC has already gained widespread adoption among organizations and products such as Netflix, Cloudflare, Google, Docker & Slack etc. Its ability to offer Bi-directional streaming with HTTP/2 in a consistent yet language-idiomatic manner has been a key factor in its adoption.
gRPC is a modern open-source, high-performance Remote Procedure Call (RPC) framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking, and authentication. It is also applicable in the last mile of distributed computing to connect devices, mobile applications, and browsers to backend services.
How is it better than REST?
REST APIs, or Representational State Transfer Application Programming Interfaces, are a set of architectural principles and constraints used for designing networked applications. It is completely different than that of gRPC which runs on HTTP verbs like GET, POST, PUT, DELETE, etc., and takes serialized text-based parameters as input (either JSON or XML). However, for a very simple straightforward API, REST is more suitable, but in real-world applications where tons of data are involved gRPC is way ahead of REST. Let’s find out the reasons behind that.
- HTTP Protocol – By default REST uses HTTP/1.1 protocol and gRPC uses HTTP/2 protocol which allows to use of features like streaming, multiplexing & sending smaller message sizes due to binary framing.
- Transfer Data Format – gRPC uses a Protocol Buffer (binary format data) while transferring serialized data either way (Client -> Server -> Client) other than text-based JSON or XML. This allows gRPC to transfer data faster than REST as it is more efficient & less verbose.
- Client Server Communication – In REST, request & response are independent of HTTP messages, whereas in gRPC it is a more persistent connection and stream that allows multiple messages to be sent either way simultaneously.
- API Contract – REST uses Open API/Swagger to define its requests & responses. And gRPC uses proto files which are simpler and concise and developer friendly.
- Client-side Consumption – Unlike REST, gRPC does not work upon different HTTP verbs. Using the proto file client can create its classes and methods which will be used as services. So, for gRPC it is like calling a method within the same application for developers. Here, client and server can be built on different programming languages as long as those support protocol buffer method.
- Scalability – gRPC can scale linearly which provides an extra scale in terms of the high availability of the application.
- Performance – gRPC is better for data-heavy applications with top-notch data services. The below comparison shows for different numbers of requests REST is far behind gRPC.
Type | 1000 Requests | 2000 Requests | 3000 Requests | 4000 Requests | 5000 Requests |
gRPC | 14.478 sec | 25.239 sec | 37.823 sec | 53.073 sec | 62.624 sec |
REST | 16.451 sec | 30.181 sec | 43.996 sec | 58.221 sec | 71.300 sec |
Where should you use gRPC and where not?
Opting for gRPC proves advantageous when constructing microservices that demand high performance, optimal speed, minimal latency, and scalability in communication between client and server. This technology excels in scenarios necessitating real-time data streaming, bidirectional communication, and high-throughput requirements.
However, gRPC is not the ideal choice for scenarios seeking a straightforward and lightweight API or those aiming for extensive interoperability with systems using diverse protocols. Similarly, it is not recommended for situations demanding a high level of flexibility concerning message formats and data types. Also due to the proto configuration, a learning curve will be there for developers.
Implementation of gRPC service using .NET Core
As we already know gRPC has two modules.
- gRPC Server
- gRPC Client
.NET Core supports both of these from Visual Studio 2019. So, let’s see how we create and consume gRPC services using .NET Core.
gRPC Server
To start a gRPC project in Visual Studio/Visual Studio Code, you have to select the gRPC template while creating a new project. Or you can run the below command to create a new gRPC service.
Once the project is created, install three NuGet packages from the Package Manager Console.
dotnet add package Grpc.AspNetCore
dotnet add package Google.Protobuf
dotnet add package Grpc.Tools
Now your project is ready to act as a gRPC service. It is time to add your first service in gRPC.
Let’s say you have to build a Customer Service where you need to expose a procedure to create customers. So, create a proto file and set the Service name, request & response over there.
syntax = "proto3";
option csharp_namespace = "GrpcCustomerService";
// exposed service
service CustomerService {
rpc CreateCustomer (CustomerRequest) returns (CustomerResponse);
}
// request
message CustomerRequest {
string name = 1;
string email = 2;
string mobile = 3;
}
// response
message CustomerResponse {
string message = 1;
}
While you are adding this proto file, make sure it is included in your project (.csproj) file.
Now implement the actual service. Create a new C# file named CustomerService.cs and add a class named CustomerService. Implement the class from CustomerServiceBase.
Don’t forget to build your project after creating the proto file and before creating the service class. If you don’t build your solution, CustomerSeviceBase won’t be available to inherit.
Please note, that CustomerSeviceBase is an auto-generated class stored in your obj folder in the bin. Every time it’s recreated by the .NET compiler whenever there are any changes in the proto file. The same is happening for gRPC clients also.
using Grpc.Core
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
public class CustomerService : CustomerServiceBase
{
private readonly ILogger<CustomerService> _logger;
public CustomerService(ILogger<CustomerService> logger)
{
_logger = logger;
}
public override Task<CustomerResponse> CreateCustomer(CustomerRequest request, ServerCallContext context)
{
// TODO - Your logic to create a customer goes here
return Task.FromResult(new CustomerResponse
{
Message = $"Customer {request.Name} created successfully!"
});
}
}
To enable the gRPC service, in your Program.cs file add the gRPC service.
services.AddGrpc();
And create an endpoint for the gRPC CustomerService.
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<CustomerService>();
});
Now build your code and run. In the console, you will get the endpoint (https://localhost:5001) where your gRPC service is running.
gRPC Client
And add the below-mentioned NuGet packages. These are specially for gRPC clients.
dotnet add package Grpc.Net.Client
dotnet add package Google.Protobuf
dotnet add package Grpc.Tools
Once the installation of these NuGet packages is done, create the proto file using the server file. It will be an exact replica of the server one.
Build your project and run the below dotnet command to generate a gRPC client using the proto file.
dotnet grpc compile
Now create the client file from where you are going to consume the CreateCustomer method of Customer Service.
static async Task Main(string[] args)
{
// Specify the gRPC server address – Need to set this from applicationSettings.json
var channel = GrpcChannel.ForAddress("https://localhost:5001");
// Create a gRPC client for the CustomerService
var client = new CustomerService.CustomerServiceClient(channel);
// Your customer data
var request = new CustomerRequest
{
Name = "Test Name",
Email = "[email protected]",
Mobile = "987654310"
};
// Call the CreateCustomer method on the gRPC service
var response = await client.CreateCustomerAsync(request);
// Display the response
Console.WriteLine($"Server says: {response.Message}");
}
Run both your projects (set the server as a top priority) and in the console, you will get the desired result.
Conclusion
In summary, gRPC is a good choice for building high-performance, low-latency, and scalable microservices that require efficient communication between client and server. It is especially well-suited for use cases that involve real-time data streaming, bi-directional communication, and high-throughput scenarios. However, it is not recommended for use cases that require a simple and lightweight API, or for use cases that require a high degree of interoperability with other systems that use different protocols. It is also not recommended for use cases that require a high degree of flexibility in terms of message formats and data types.