Table of Contents

gRPC

This tutorial will teach you the basics of using gRPC in your services.

Prerequisites

  1. Windows 10/11
  2. Visual studio 2019/2022
  3. Phoesion Glow Blaze , with Reactor running (see getting started guide)

Sample Code

You can download the Sample Code archive from the downloads section.
This tutorial follows the 14_gRPC sample in the archive. (View code on GitHub)

Introduction

The Phoesion Glow system provides a build-in mechanism for easily creating gRPC enabled endpoints. gRPC is a modern open source high performance Remote Procedure Call (RPC) framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking and authentication. It is also applicable in last mile of distributed computing to connect devices, mobile applications and browsers to backend services.

For more information about the gRPC protocol you can read here.

Creating the API

The first thing we need to do in our API project is install the NuGet packages Google.Protobuf and Grpc.Tools. These will generate the appropriate code from our .proto files. Next we need to create our .proto file that will contain the Data Transfer Object (DTO) for our request/response.

Create a new SampleModule1.proto file with the following content :

syntax = "proto3";

package Foompany.Services.API.SampleService1.Modules.SampleModule1.Dto;

// The request message containing the user's name.
message HelloRequest {
   string InputName = 1;
}

// The response message containing the greetings.
message HelloReply {
   string Result = 1;
}

After building the project, the new classes will be available for use. Create the API class for the module action prototypes normally. (See Writing API prototypes for Modules for more)

gRPC enabled actions

Now we are ready to create our gRPC enabled action in our Firefly Module, by using the Methods.gRPC method, like so :

[ActionBody(Methods.gRPC)]
public dto.HelloReply DoTheThing(dto.HelloRequest request)
{
    return new dto.HelloReply()
    {
        Result = $"Hello {request.InputName}, i did the thing!"
    };
}
Note

We can expose the action for other methods at the same time like so [ActionBody(Methods.POST | Methods.gRPC)] This will allow our action to be consumed by both gRPC and HTTP Post consumers!

Client-Side

To consume the API we create, we can use gRPC normally from our client (it's Glow agnostic).

  • First we create a simple console application that will be our client and install the Google.Protobuf, Grpc.Tools and Grpc.Net.Client NuGet packages.

  • Create a SampleService1.SampleModule1.proto file with the content:

syntax = "proto3";

// Package name must match the module API type namespace
package Foompany.Services.API.SampleService1.Modules.SampleModule1;

// The request message containing the user's name.
message HelloRequest {
  string InputName = 1;
}

// The response message containing the result.
message HelloReply {
  string Result = 1;
}

// The service definition. This must match exactly the class name of the module API type
service Actions {

// Sends a greeting
  rpc DoTheThing (HelloRequest) returns (HelloReply);

  // Stream results sample
  rpc StreamResultsSample (HelloRequest) returns (stream HelloReply);
}
  • Call our api using :
private async Task call_service()
{
    try
    {
        //----------------------------------------
        // NOTE: gRPC requires HTTP/2 and SSL
        //----------------------------------------
        //create gRPC client, targeting the SampleService1/SampleModule1 api
        using var channel = GrpcChannel.ForAddress($"https://localhost");
        var client = new Services.API.SampleService1.Modules.SampleModule1.Actions.ActionsClient(channel);

        //create request
        var req = new HelloRequest { InputName = txt_SampleInput.Text };

        //call 
        var reply = await client.DoTheThingAsync(req);

        //show results
		Console.WriteLine($"Got Response : {reply.Result}");
    }
    catch (Exception ex) { MessageBox.Show($"Error : {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); }
}