# gRPC
# What does it mean?
g | gRPC |
---|---|
R | Remote |
P | Procedure |
C | Calls |
g = Google |
# What is it used for?
- Client ⇔ Server Communication
- Server ⇔ Server Communication
- X ⇔ Y Communication
# Transport channel (ツ)
gRPC is agnostic about the transport channel.
For client server communication in a web application we use gRPC over HTTP.
# Why use it rather than [X] ?
- Efficient serialization → Small message size
- Interface definition can easily be shared (.protobuf files)
- Support for both server-side code generation and client generation for many languages
- Integrating systems in different languages
# Programming Model
ClientServerDoSomething()responseDataClientServer
A client application calls a method on a server application on a different machine as if it were a local object.
# Multiple Different Clients
MethodCall()ResponseMethodCall()ResponseClient AC#Client BC++ServerC#
# Message Format
By default, gRPC uses Protocol Buffers
// This is how you define services and message types.
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string firstName = 1;
string lastName = 2;
}
message HelloReply {
string greeting = 1;
}
# Adding gRPC and Protobuf to a .NET Solution
You need three projects.
- Install NuGet Packages in Shared project:
Grpc.Net.Client
Google.Protobuf
Grpc.Tools
- Add folder
Grpc
in Shared project - Add reward.proto file in that folder
// File: reward.proto
syntax = "proto3";
option csharp_namespace = "SavingsPlanner.Shared.Grpc";
package Rewards;
service Rewards {
rpc GetRewards (RewardRequest) returns (RewardReply);
}
message RewardRequest {}
message RewardReply {
repeated RewardItem rewards = 1;
}
message RewardItem {
int32 id = 1;
string title = 2;
double targetAmount = 3;
string description = 4;
}
Add code in Shared .csproj file
<ItemGroup>
<Protobuf
Include="Grpc/reward.proto"
GrpcServices="Server,Client">
</Protobuf>
</ItemGroup>
- Install NuGet Packages in Client project:
Grpc.Net.Client.Web
// Add in Program.cs of client project
builder.Services.AddSingleton(services =>
{
var httpClient = new HttpClient(
new GrpcWebHandler(
GrpcWebMode.GrpcWeb,
new HttpClientHandler()));
var baseUri = services
.GetRequiredService<NavigationManager>()
.BaseUri;
var channel = GrpcChannel
.ForAddress(
baseUri,
new GrpcChannelOptions { HttpClient = httpClient });
return new Rewards.RewardsClient(channel);
});
If you have a seperate Client-Server architecture - add the following line:
builder.Services.AddSingleton(services =>
{
var httpClient = new HttpClient(
...
!--
var baseUri = @"http://localhost:5125";
!--
var channel = GrpcChannel
...
return new School.SchoolClient(channel);
});
// in a Blazor component on the client
@inject Rewards.RewardsClient RewardsClient
private async Task LoadDataAsync()
{
var rewardsResponse =
await RewardsClient.GetRewardsAsync(new RewardsRequest());
rewards = rewardsResponse.Rewards.ToArray();
}
- Install NuGet Packages in Server project:
Grpc.AspNetCore.Web
Grpc.AspNetCore
- Implement a service by deriving from generated classes in Shared project (next slide)
public class RewardService : Rewards.RewardsBase
{
private readonly IRepository<Reward> _repository;
public override async Task<RewardReply> GetRewards(
RewardRequest request, serverCallContext context)
{
var reply = new RewardReply();
var items = await _repository.GetAllAsync<RewardItem>();
reply.Rewards.AddRange(items);
return reply;
}
}
// in Program.cs of Server project
builder.Services.AddGrpc();
app.UseGrpcWeb();
app.MapGrpcService<RewardService>().EnableGrpcWeb();
// Automapper configuration
// for transformation to generated type
CreateMap<Reward, RewardItem>()
.ForMember(
r => r.TargetAmount,
opt => opt.MapFrom(src => (double)src.TargetAmount));