Working With gRPC in .Net. gRPC
Tags: Benchmark, Grpc, Rest, Aspnetcore

gRPC

gRPC is a high-performance Remote Procedure Call (RPC) framework. Similar like SOAP it uses a Contract-first approach to API development. It uses Protocol buffers (protobuf) to define services and messages sent between Client and servers. Protobuf messages are defined in .proto files.

The main benefits of gRPC are:

It’s modern lightweight Contract first API development using Protocol Buffers which uses binary serialization to transfer data. It mainly helps to reduce network usage.

You can use multiple languages to develop contracts and clients to call the services (protobuf supports wide range of programming languages) and has strongly-typed servers and clients.

gRPC supports Clinet, server calls like REST and also supports bi-directional streaming calls where real-time services that need to handle streaming requests or responses.

REST VS gRPC

REST:

REST is a popular resource based technique using HTTP Verbs HTTP GET,HTTP POST,HTTP PUT,HTTP PACTH,HTTP DELETE to perform CURD operations. REST’s communication often includes sending a JSON and can run over HTTP/1.1 or HTTP/2.

It is easy to develop a RESTful web service and it has browser support to perform action over Web Clients from Browser.

Major Communication happens using a JSON or XML, which is human readable. This makes it easier for developers to determine if the client input was sent correctly to the server and back, but it is too large to parse data.

REST is also widely used. A lot of people have experience with it and a lot of other web services (and clients) use REST. Having a REST web service makes it easier for other people to interact with your web service.

We don’t need any client setup to make calls to the server.

gRPC

gRPC is an open-source RPC framework that is created and used by Google. It is built upon HTTP/2 which makes bi-directional communication possible. gRPC communicates using binary data using protocol buffers by default for serializing structured data. gRPC servers allow cross-language unary calls or stream calls.

gRPC can use protocol buffer for data serialization. This makes payloads faster, smaller and simpler.

Just like REST, gRPC can be used cross-language which means that if you have written a web service in Golang, a Java written application can still use that web service, which makes gRPC web services very scalable.

gRPC uses HTTP/2 to support highly performant and scalable API’s and makes use of binary data rather than just text which makes the communication more compact and more efficient. gRPC makes better use of HTTP/2 then REST. gRPC for example makes it possible to turn-off message compression. This might be useful if you want to send an image that is already compressed. Compressing it again just takes up more time.

It is also type-safe. This basically means that you can’t give an apple while a banana is expected. When the server expects an integer, gRPC won’t allow you to send a string because these are two different types.

gRPC has Support to Java Script from web. It is easy to make calls form Browser using gRPC web library.

Protos

gRPC uses Protobuf as its Interface Definition Language (IDL). Protobuf IDL is a language neutral format for specifying the messages sent and received by gRPC services and Contract Defined in a Service for Communication.

Protobuf has Special syntax to define contracts and messages to Generate Services and .Net Models to communicate. When we define Contracts and Messages in protos .Net will generate a code into Managed C# language using Grpc.Tools Library.

Protobuf supports a range of native scalar value types that are equivalent C# type, but with having wide range types in C#, there is a limitation to have them converted into specific types. example:(The native scalar types don’t provide for date and time values, equivalent to .NET’s DateTimeOffset, DateTime, and TimeSpan. These types can be specified by using some of Protobuf’s Well-Known Types extensions). We have some missed types like Decimal in native support.

Proto Example:

namespace Practice

{

public class Product

{

public int ProductId { get; set;}

public string ProdcutName { get; set;}

public string Description { get; set;}

public int SKU { get; set; }

}

}

To Define C# model in Proto message we have equalent syntax below.

syntax = "proto3"; option csharp_namespace = "Practice"; import "google/protobuf/empty.proto"; service Products{

rpc GetProducts(google.protobuf.Empty) returns (Response);

} message Response{

repeated Product products = 1;

Status status = 2;

} enum Status {

Success = 0;

Failure = 1;

Unknown = 2;

} message Product{ int32 product_id = 1;

string prodcut_name = 2;

string sescription = 3;

int32 SKU = 4; }

In the above protobuf file, every Key has their own field number, those are very important in Proto files. They’re used to identify fields in the binary encoded data, which means they can’t change from version to version of your service. The advantage is that backward compatibility and forward compatibility are possible. Clients and services will simply ignore field numbers that they don’t know about, as long as the possibility of missing values is handled.

In binary format, the field number is combined with a type identifier. Field numbers from 1 to 15 can be encoded with their type as a single byte. Numbers from 16 to 2,047 take 2 bytes. You can go higher if you need more than 2,047 fields on a message for any reason. Single byte identifiers for field numbers 1 to 15 offer better performance, so you should use them for the most basic and frequently used fields.

Error handing

While developing services, it is best practice to provide better information when something is wrong with processing a request by throwing an error to caller giving valid information about the request.

gRPC has own Exception type to provide information about exception happened while processing request. By providing a valid Status code and Error message to the client we can have better information about What’s Wrong with the request or Server.

Similar RESTful services are sending Status code to client about the request processing errors like Model State is not valid or Unauthorized request. gRPC also have different status code to give the information. An ASP.NET Core gRPC service can send an error response by throwing an RpcException, which can be caught by the client as if it were in the same process. The RpcException must include a status code and description, and can optionally include metadata and a longer exception message.

Raise errors in ASP.NET Core gRPC

public async Task<Empty> CreateProduct(Product request, ServerCallContext context)

{

if (CheckForProductExists(request.ProductId))

{

var metadata = new Metadata

{

{ "Product", request.ProductId }

};

throw new RpcException(new Status(StatusCode.AlreadyExists, "Product Already Exists"), metadata);

}

}

Catch errors in gRPC clients