Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Microservices Communication in .NET Using gRPC

You're reading from   Microservices Communication in .NET Using gRPC A practical guide for .NET developers to build efficient communication mechanism for distributed apps

Arrow left icon
Product type Paperback
Published in Feb 2022
Publisher Packt
ISBN-13 9781803236438
Length 486 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Fiodar Sazanavets Fiodar Sazanavets
Author Profile Icon Fiodar Sazanavets
Fiodar Sazanavets
Arrow right icon
View More author details
Toc

Table of Contents (17) Chapters Close

Preface 1. Section 1: Basics of gRPC on .NET
2. Chapter 1: Creating a Basic gRPC Application on ASP.NET Core FREE CHAPTER 3. Chapter 2: When gRPC Is the Best Tool and When It Isn't 4. Chapter 3: Protobuf – the Communication Protocol of gRPC 5. Section 2: Best Practices of Using gRPC
6. Chapter 4: Performance Best Practices for Using gRPC on .NET 7. Chapter 5: Applying Versioning to the gRPC API 8. Chapter 6: Scaling a gRPC Application 9. Section 3: In-Depth Look at gRPC on .NET
10. Chapter 7: Using Different Call Types Supported by gRPC 11. Chapter 8: Using Well-Known Types to Make Protobuf More Handy 12. Chapter 9: Securing gRPC Endpoints in Your ASP.NET Core Application with SSL/TLS 13. Chapter 10: Applying Authentication and Authorization to gRPC Endpoints 14. Chapter 11: Using Logging, Metrics, and Debugging in gRPC on .NET 15. Assessments 16. Other Books You May Enjoy

Setting up a gRPC client

Now, we will add a basic gRPC client that will be able to communicate with our service via gRPC. This will be a basic console application. The process will consist of the following steps:

  1. Initialize the console application project.
  2. Add some gRPC client dependencies to the project.
  3. Add some code to connect to the gRPC client.

Once you've followed these steps, your basic console application will be able to send requests to the gRPC server and receive responses from it.

Initializing the project for the client application

If you are using an IDE, you can add a new project to your solution. The template that you will need is called Console Application or Console Project, depending on which IDE you're using. However, you need to make sure that you don't choose the .NET Framework version of the template, which will be clearly labeled. Likewise, make sure that you select the C# template as the IDE may present you with options for other languages too:

Figure 1.9 – Console Application template on Visual Studio 2019

Figure 1.9 – Console Application template on Visual Studio 2019

As console application is a very basic application type; there won't be any complex setup options to select while creating the project. You can leave all the default options selected. Let's call our new project BasicGrpcClient.

If you are using a code editor and CLI instead of a fully-fledged IDE, you can create the project by executing a dotnet CLI command. Please ensure that you execute this command from the folder where the BasicGrpcService project folder is located. It will create the new project folder at the same level inside of your filesystem that your original project folder is located at. The command will be as follows:

dotnet new console -o BasicGrpcClient

Adding gRPC client components to the application

Now, to make your console application act as a gRPC client, you will need to add some NuGet references to your project. You can do so by executing the following commands inside your BasicGrpcClient project folder:

dotnet add BasicGrpcClient.csproj package Grpc.Net.Client
dotnet add BasicGrpcClient.csproj package Google.Protobuf
dotnet add BasicGrpcClient.csproj package Grpc.Tools

Once the packages have been installed, the content of your BasicGrpcClient.csproj file should be similar to this:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Google.Protobuf"
      Version="3.17.3" />
    <PackageReference Include="Grpc.Net.Client"
      Version="2.38.0" />
    <PackageReference Include="Grpc.Tools" Version="2.38.1">
      <IncludeAssets>runtime; build; native; contentfiles; 
        analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
  </ItemGroup>
</Project>

Next, we will need to add the following section to the project file, which references the proto file we will be using to communicate with the server:

  <ItemGroup>
    <Protobuf Include="Protos\greeter.proto"
      GrpcServices="Client" 
      />
  </ItemGroup>

This will make our project file look like this:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Google.Protobuf"
      Version="3.17.3" />
    <PackageReference Include="Grpc.Net.Client"
      Version="2.38.0" />
    <PackageReference Include="Grpc.Tools" Version="2.38.1">
      <IncludeAssets>runtime; build; native; contentfiles; 
        analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
  </ItemGroup>
  <ItemGroup>
    <Protobuf Include="Protos\greeter.proto"
      GrpcServices="Client" />
  </ItemGroup>
</Project>

This is similar to what we've done with the server application. But this time, we are telling our application to only generate code for the client components. This is why we have set the GrpcServices attribute to Client.

Because we will be connecting to the server we created previously, we need a proto file with package, service, rpc, and message definitions that are identical to what we had in our server-side proto file. However, our C# namespace can be different.

Therefore, what you'll need to do next is create a Protos folder inside your BasicGrpsClient project folder. Then, you must insert the greeter.proto file into this folder and ensure it has the following content:

syntax = "proto3";
option csharp_namespace = "BasicGrpcClient";
 package greeter;
 
// The greetings manager service definition.
service GreetingsManager {
  // Request the service to generate a greeting message.
  rpc GenerateGreeting (GreetingRequest) returns 
    (GreetingResponse);
}
 
// The request message definition containing the name to be 
  addressed in the greeting message.
message GreetingRequest {
  string name = 1;
}
 
// The response message definition containing the greeting   text.
message GreetingResponse {
  string greetingMessage = 1;
}

Please note that this file is identical to the one we have in our server application project, except for the csharp_namespace element. This element is used by the gRPC tools inside your specific .NET project and it does not affect compatibility between the server and client versions of the proto file. However, the rest of the elements must be the same for the communication system to recognize that it's meant to be the same interface.

Some differences are tolerated (which we will talk about when we cover API versioning in Chapter 5, How to Apply Versioning to the gRPC API). But the fundamental structure of your standard gRPC element definitions must match.

Applying gRPC client components to the code

In your BasicGrpcClient project, locate the Program.cs class and change its content to the following:

using System;
using System.Threading.Tasks;
using Grpc.Net.Client;
namespace BasicGrpcClient
{
    class Program
    {
        static async Task Main()
        {
             // The port number(5001) must match the port of 
             the gRPC server.
            using var channel = 
            GrpcChannel.ForAddress("https://localhost:5001");
            var client = new 
            GreetingsManager.GreetingsManagerClient(channel);
            var reply = await client.GenerateGreetingAsync(
            new GreetingRequest { Name = "BasicGrpcClient" });
            Console.WriteLine("Greeting: " + reply.
              GreetingMessage);
            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
    }
}

Please note that the highlighted URL represents the HTTPS access point to the gRPC server. This will not be available if you are running your software on Mac. The workaround to this is described in the Running a gRPC service on Mac section of this chapter.

This code does the following:

  1. First, it initializes the gRPC channel for the hardcoded address of https://localhost:5001. Please note that this is the same address that we defined in the launchSettings.json file in the BasicGrpcService project. But in a real commercial application, this will be configurable rather than hardcoded.
  2. Then, it uses this channel to initialize a new instance of the gRPC client that was generated by the GreetingsManager service definition in our greeter.proto file.
  3. Next, it calls the GenerateGreetingAsync method of the client object with a new instance of GreetingRequest that has its Name property set to BasicGrpcClient. Please note that it represents the GenerateGreeting rpc definition from the proto file, but the Async part has been added to the name. This is because, in .NET, each gRPC procedure is represented by synchronous and asynchronous methods on the client side. The async version returns an awaitable task, so the calling code can be set to do something else while we are waiting for the reply. The synchronous version, which has the same name as the original rpc definition but without "Async" at the end, blocks execution of the calling code until the result has been received.
  4. From this call, we receive an instance of GreetingResponse.
  5. Then, we read the value of its GreetingMessage field and print it in the console.
  6. Finally, the console prompts the user to press any key to exit.

Now, you can launch both of your applications and see how they communicate with each other. It's better to launch the server application first to make sure that it has fully loaded before the client application tries to communicate with it.

The simplest way to launch both applications is to open two instances of the command-line window (cmd, PowerShell, or Terminal, depending on your operating system and your preferences). In one command-line window, navigate to the BasicGrpcService project folder and execute the following command:

dotnet run

This will build and run the server application for you. Once it's showing the output that indicates that the gRPC server is running, open the other instance of the command-line window, navigate to the BasicGrpcClient project folder, and execute the same command.

You should receive the following output, which indicates that the client was able to successfully call the method on the server via the network:

Figure 1.10 – Console output from the gRPC client application

Figure 1.10 – Console output from the gRPC client application

Now, if you re-examine the code from your client and your server, you will see that it looks almost as if you are calling the code from inside the same application. And that's precisely what makes gRPC so easy to use.

In both the applications that we covered, you saw how relevant code is automatically generated from proto files. In certain scenarios, it would be useful to know how this mechanism works. This is what we will have a look at now.

You have been reading a chapter from
Microservices Communication in .NET Using gRPC
Published in: Feb 2022
Publisher: Packt
ISBN-13: 9781803236438
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime