Tuesday 30 November 2021

Microservice API using gRPC on .NET

 gRPC is a hot cake now for Microservices development. it is a high-performance, lightweight RPC framework for Microservices development. It uses Contract-first API development, using Protocol Buffers by default, allowing for language agnostic implementations. Protobuf (Protocol Buffers) binary serialization reduces the network usage which makes it highly performative.

gRPC is based on Remote Procedure Call (RPC) pattern, uses HTTP/2 protocol for communication and uses three basic concepts Channel, Remote Procedure calls (streams) and Messages.

A channel can have multiple RPCs (streams) and a stream is a collection of many messages.

Like gRPC, Windows Communication Framework (WCF) also based on Remote Procedure Call (RPC) pattern but gRPC and WCF differs in many ways. Lets see how they differ:

How to create gRPC Service

syntax = "proto3";import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";
option csharp_namespace = "GrpcServiceDemo";package weatherForcast;// The weather forecast service definition.
service WeatherForcast {
// Get weather forecast
rpc GetWeatherForecast (google.protobuf.Empty) returns (WeatherForecastReply);
rpc GetWeatherForecastForDate (google.protobuf.Timestamp) returns (WeatherForecastReply);}// The response message containing the weather information.
message WeatherForecastReply {
repeated WeatherForecast Result = 1;
}
message WeatherForecast {
google.protobuf.Timestamp Date = 1;

int32 TemperatureC = 2;

int32 TemperatureF = 3;

string Summary = 4;
}
<ItemGroup>
<Protobuf Include="Protos\weatherForecast.proto" GrpcServices="Server" />
</ItemGroup>
using System.Threading.Tasks;
using Google.Protobuf.WellKnownTypes;
using Grpc.Core;
using GrpcServiceDemo;
namespace GrpcServiceDemo.Services
{
public interface IWeatherForecastService
{
Task<WeatherForecastReply> GetWeatherForecast(ServerCallContext context);
Task<WeatherForecastReply> GetWeatherForecastForDate(Timestamp date, ServerCallContext context); }
}
using Grpc.Core;
using GrpcServiceDemo;
using Google.Protobuf.WellKnownTypes;
namespace GrpcServiceDemo.Services
{
public class WeatherForecastService : IWeatherForecastService
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastService> _logger;public WeatherForecastService(ILogger<WeatherForecastService> logger)
{
_logger = logger;
}
public Task<WeatherForecastReply> GetWeatherForecast(ServerCallContext context)
{
return Task.FromResult<WeatherForecastReply>(GetWeather());
}
public Task<WeatherForecastReply> GetWeatherForecastForDate(Timestamp date, ServerCallContext context)
{
return Task.FromResult<WeatherForecastReply>(GetWeather(date));
}
private WeatherForecastReply GetWeather()
{
var result = new WeatherForecastReply();
for (var index = 1; index <= 5; index++)
{
result.Result.Add(
new WeatherForecast
{
Date = Timestamp.FromDateTime(DateTime.UtcNow.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)],
TemperatureF = (int)(32 + (Random.Shared.Next(-20, 55) / 0.5556))
}
);
}
return result;
}
private WeatherForecastReply GetWeather(Timestamp date)
{
var result = new WeatherForecastReply();
result.Result.Add(
new WeatherForecast
{
Date = date,
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)],
TemperatureF = (int)(32 + (Random.Shared.Next(-20, 55) / 0.5556))
}
);
return result;
}
}
}
using Grpc.Core;
using Google.Protobuf.WellKnownTypes;
namespace GrpcServiceDemo.Services
{
public sealed class WeatherForecastGrpcService : WeatherForcast.WeatherForcastBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastService> _logger;
private readonly IWeatherForecastService _weatherForecastService;
public WeatherForecastGrpcService(ILogger<WeatherForecastService> logger, IWeatherForecastService weatherForecastService)
{
_logger = logger;
_weatherForecastService = weatherForecastService;
}
public override Task<WeatherForecastReply> GetWeatherForecast(Empty request, ServerCallContext context)
{
return _weatherForecastService.GetWeatherForecast(context);
}
public override Task<WeatherForecastReply> GetWeatherForecastForDate(Timestamp date, ServerCallContext context)
{
return _weatherForecastService.GetWeatherForecastForDate(date, context);
}
}
}
using GrpcServiceDemo.Services;var builder = WebApplication.CreateBuilder(args);// Add services to the container.
builder.Services.AddGrpc();
builder.Services.AddTransient<IWeatherForecastService, WeatherForecastService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
app.MapGrpcService<WeatherForecastGrpcService>();
app.Run();

How to create gRPC Service Client

<ItemGroup>
<Protobuf Include="Protos\weatherForecast.proto" GrpcServices="Client" />
</ItemGroup>
using Google.Protobuf.WellKnownTypes;
using Grpc.Net.Client;
using GrpcServiceDemo;
// The port number must match the port of the gRPC server.
using var channel = GrpcChannel.ForAddress("https://localhost:7001");
var weatherClient = new WeatherForcast.WeatherForcastClient(channel);var request = new Google.Protobuf.WellKnownTypes.Empty();
var weatherInfo = weatherClient.GetWeatherForecast(request);
Console.WriteLine("*****Weather forecast for 5 days*****");
Console.WriteLine(weatherInfo.Result);
weatherInfo = weatherClient.GetWeatherForecastForDate(Timestamp.FromDateTime(DateTime.UtcNow));
Console.WriteLine("*****Weather forecast for today*****");
Console.WriteLine(weatherInfo.Result);
request = new Google.Protobuf.WellKnownTypes.Empty();
weatherInfo = await weatherClient.GetWeatherForecastAsync(request);
Console.WriteLine("*****Weather forecast for 5 days*****");
Console.WriteLine(weatherInfo.Result);
weatherInfo = await weatherClient.GetWeatherForecastForDateAsync(Timestamp.FromDateTime(DateTime.UtcNow));
Console.WriteLine("*****Weather forecast for today*****");
Console.WriteLine(weatherInfo.Result);
Console.ReadKey();

No comments:

Post a Comment