gRPC in .NET Core 3.0
While writing this post .NET Core 3.0.100-preview6 is available. As this is still in preview it is going to change in future.
Recent years there is a quick rise in usage of Microservice architecture. Initially there is a SOAP based service for distributed system then REST. As Microservice architecture there is case when service needs to communicate with each other efficiently. To solution to this gRPC become more evident. At the end of this post I have provided few article that is useful.
Currently .NET Core 3.0 has added functionality for gRPC and in this article I am going to provide sample using .NET Core 3.0.100-preview6 and Docker. ( You can do this in your bare mettle machine but as .NET Core still in preview I don't want to take risk).
Note: Docker for Windows (With Linux container) is being used for this example.
- Get .NET Core 3.0.100-preview6 image from dockerhub.
docker pull mcr.microsoft.com/dotnet/core/sdk:3.0.100-preview6
- Create GrpcGreetServer. Create Container with interactive mode.
C:\Windows\system32>docker run --name GrpcGreetServer -it mcr.microsoft.com/dotnet/core/sdk:3.0.100-preview6 /bin/bash
root@198bfb5e759e:/# dotnet --version
3.0.100-preview6-012264
root@198bfb5e759e:/# dotnet new grpc -o GrpcGreeter
Getting ready...
The template "ASP.NET Core gRPC Service" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on GrpcGreeter/GrpcGreeter.csproj...
Restore completed in 2.03 min for /GrpcGreeter/GrpcGreeter.csproj.
Restore succeeded.
root@198bfb5e759e:/# cd GrpcGreeter/
root@198bfb5e759e:/GrpcGreeter# dotnet run
warn: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to bind to http://localhost:50051 on the IPv6 loopback interface: 'Cannot assign requested address'.
info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://localhost:50051
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: /GrpcGreeter
Now copy project from container to host and build docker image. ( I assume that in host it is being copied to C:\Test\GrpcGreetServer)
docker cp GrpcGreetServer:/GrpcGreeter GrpcGreetServer
Build Image with help following Dockerfile. ( This is not optimized dockerfile).
FROM mcr.microsoft.com/dotnet/core/sdk:3.0.100-preview6 AS build-env
WORKDIR /app
EXPOSE 80
# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/core/sdk:3.0.100-preview6
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "GrpcGreeter.dll"]
To Build image ( run following command from c:\test\grpcgreetserver)
docker build -t grpcserver .
Now build client application. once complete this.
C:\Test>docker run --name GrpcGreetClient -it mcr.microsoft.com/dotnet/core/sdk:3.0.100-preview6 /bin/bash
root@fc49a48e55eb:/# dotnet --version
3.0.100-preview6-012264
root@fc49a48e55eb:/# dotnet new console -o GrpcGreeterClient
Getting ready...
The template "Console Application" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on GrpcGreeterClient/GrpcGreeterClient.csproj...
Restore completed in 58.73 ms for /GrpcGreeterClient/GrpcGreeterClient.csproj.
Restore succeeded.
root@fc49a48e55eb:/# cd GrpcGreeterClient/
root@fc49a48e55eb:/GrpcGreeterClient# dotnet add GrpcGreeterClient.csproj package Grpc.Net.Client -v 0.1.22-pre1
root@fc49a48e55eb:/GrpcGreeterClient# dotnet add GrpcGreeterClient.csproj package Google.Protobuf
root@fc49a48e55eb:/GrpcGreeterClient# dotnet add GrpcGreeterClient.csproj package Grpc.Tools
root@fc49a48e55eb:/GrpcGreeterClient# exit
Now copy to local (host) machine. ( This copied to C:\Test\GrpcGreeterClient)
docker cp GrpcGreetClient:/GrpcGreeterClient GrpcGreeterClient
Now add following things. Update program.cs
using System;
using System.Net.Http;
using System.Threading.Tasks;
using GrpcGreeter;
using Grpc.Net.Client;
namespace GrpcGreeterClient
{
class Program
{
static async Task Main(string[] args)
{
AppContext.SetSwitch(
"System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport",
true);
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("http://172.17.0.2:80");
var client = GrpcClient.Create<Greeter.GreeterClient>(httpClient);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}
add Dockerfile to GrpcGreeterClient folder.
FROM mcr.microsoft.com/dotnet/core/sdk:3.0.100-preview6 AS build-env
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/core/sdk:3.0.100-preview6
WORKDIR /app
COPY --from=build-env /app/out .
CMD ["dotnet", "GrpcGreeterClient.dll"]
Following are some good articles bugsnag.com/blog/grpc-and-microservices-arc.. hackernoon.com/rest-in-peace-grpc-for-micro.. grpc.io/docs/guides