HomeAuthorsContact
gRPC - Démonstration

gRPC - Démonstration

By Frédéric Schmidt
May 21, 2020
5 min read

Introduction

Here we will get to the heart of the matter with an example of using gRPC and using first the GO language, so I start the study and that you can find in posts dedicated to the study of this powerful and pleasant Google language.

Prerequisites

Development environment

For my part, I use the following tools most simply in the world:

  • Visual Code;
  • The latest version of the GO SDK;
  • The latest version of the Protocol Buffers compiler;
  • And the essential Terminal for command lines (in my case in Visual Code).

For compiling proto in GO and gRPC for GO, you will also need to install:

  • protoc-gen-go ;
  • protoc-gen-go-grpc ;
  • codes ;
  • status ;
  • grpc ;

Demo

This basic demo will introduce the following different concepts:

  • defining our service through a file using IDL proto;
  • the generation of our server code and the code that will be used by the client in GO;
  • generate the gRPC specific code from the code generated from the proto IDL;
  • the implementation of the interface, the gRPC server;
  • Service consumption through call from our customer written in GO.

The functional purpose of the demo is not really of interest, it is mainly the implementation, the consumption of it. So to put it simply, I left on a service providing a set of basic calculation operations, such as: adding, subtracting and flipping a multiplication table some conch.

Definition of our “Protocol buffers”

Description

Here we will write all the descriptions of the messages and operations of our service using this description language. It will allow us to generate the code serving server side but also the code serving client side that can be called the service contract.

Code

syntax = "proto3";

option go_package = "fredericschmidt.fr/GoDemo01/calculatrice";

package Calculator;

service CalculatorService {
    rpc AddOperation (ValuesCalculatorRequest) returns (ResultCalculatorResponse);
    rpc SubOperation (ValuesCalculatorRequest) returns (ResultCalculatorResponse);
    rpc TableOperation (TableCalculatorRequest) returns (TableCalculatorResponse);
}

message ResultCalculatorResponse {
    int32 Result = 1;
}

message ValuesCalculatorRequest {
    int32 TermX = 1;
    int32 TermY = 2;
}

message TableCalculatorRequest {
    int32 Multiplicand = 1;
    int32 Multiplier = 2;
}

message TableCalculatorResponse {
    repeated OneLineInTableResponse LineOfTable = 1;
}

message OneLineInTableResponse {
    int32 Multiplicand  = 1;
    int32 Multiplier = 2;
    int32 Product = 3;
}

Generation

1st Step

Afterwards, we have to generate the code in GO language in our case and to do this we will execute the following command:

protoc --go_out="D:\TempDev\Lab\gRpc\goroot\src"" .\Calculatrice.proto

Then the command protoc must be if the installation was done in the directory of the variable GOBIN.

For the same reason we should also find the protoc-gen-go.exe and protoc-gen-go-grpc.exe commands. When the generation was successfully performed using the protoc command, which takes two parameters that happen to be:

  • -go _out: which is the root path where the generator will create the proto variable tree go _package in this case the root of the GOPATH source. Since with GO we are talking about package and its tree structure (see the post about structuring a project);
  • the last parameter being the proto directory and filename.
2nde Step

After that, we have to generate from the previous step the file in GO language specific to gRPC and to do this we will use the following command:

protoc --go-grpc_out="D:\TempDev\Lab\gRpc\goroot\src" .\Calculatrice.proto
  • with the following parameters:

    • —go-grpc _out: which is the root path where the generator will create the proto variable tree go _package in this case the source root of the GOPATH variable. Since with GO we are talking about package and its tree structure (see the post about structuring a project);
    • the last parameter being the proto directory and filename.

    At the end of these two steps, we obtain two GO files:

    • calculatrice_grpc_pb.go ;

    • calculatrice.pb.go.

We will come back to the content of these two files in more detail later.

Summary

To be able to use the previously generated code we need to develop two distinct parts:

  • the server part: who will listen, respond to requests and implement the contract and perform the processing according to the contract methods;
  • the client party: who will make the calls to the server and return the answers according to the contract

The server

GitHub

For the implementation code, I leave you to look directly into the sources that will be available on my GitHub.

Code Explanation

In our demonstration, the server part will implement the following methods:

type CalculatorServiceServer interface {
 AddOperation(context.Context, \*ValuesCalculatorRequest) (\*ResultCalculatorResponse, error)
 SubOperation(context.Context, \*ValuesCalculatorRequest) (\*ResultCalculatorResponse, error)
 TableOperation(context.Context, \*TableCalculatorRequest) (\*TableCalculatorResponse, error)
 mustEmbedUnimplementedCalculatorServiceServer()
 }

The next step to start and listen to the gRPC server and for this we will use the GO package about the gRPC.

We will install it using the following GO command:

go get google.golang.org/grpc 

Here is the code of the server part:

fmt.Println("Starting Calculator Server gRPC")
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("ERROR : failed to listen on port %d : %v", port, err)
}
srv := grpc.NewServer()
myPb.RegisterCalculatorServiceServer(srv, &CalculatorServer{})
if err := srv.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}

Some explanations on some lines of the code.

lis, err := net.Listen("tcp", port)

Lets you tap all the addresses available on the machine (because we didn’t specify a local address) on a specific port in a defined protocol and wait for requests.

srv := grpc.NewServer()

Asks gRPC to create a server or rather an empty shell, as there will not yet be a defined service and it will not start. And so will not yet be able to accept and process applications.

myPb.RegisterCalculatorServiceServer(srv, &CalculatorServer{})

If we look at the code generated from the IDL, we see what is called on the following line:

s.RegisterService(&_CalculatorService_serviceDesc, srv)

It allows to declare and record for our empty server shell the service contract and its implementation all this being contained in the code generated from the IDL. It is essential to do this before anything else.

The last step is to start the server so that it can process requests. Here is the part of code with a write specific to GO in the condition:

if err := srv.Serve(lis); err != nil {
 log.Fatalf("failed to serve: %v", err)
}

The instruction we are interested in is as follows: :

err := srv.Serve(lis);

She will simply tune in to our listener and process incoming requests. Each request (Transportation and Service) will be processed in a GB Routine (see GO language ticket). If a fatal error occurs during a request, the server will be closed and a fatal error will be reported.

For our demonstration, to stop the server you simply have to perform a [CTRL]+[C].

The Client

GitHub

For the implementation code, I leave you to look directly into the sources that will be available on my GitHub.

Code Explanation

I will only dwell on the parts of code specific to gRPC, the rest being more to read in the posts that are about the GO language and its specificities. In particular, on the use of the package flag for processing command line arguments.

cnx, err := grpc.Dial(uri, grpc.WithInsecure(), grpc.WithBlock())

Establish a connection to a server located at uri, in our case it will be localhost:666 and with the following options:

  • WithInsecure(): to disable transport security;

  • WithBlock(): to request that the command be blocking, because if this is not specified. The instruction returns the hand immediately and the connection is made in the background. Here we want to skip to the sequel only if the connection was made or an error.

    c:= pb.NewCalculatorServiceClient(cnx)
    

We instantiate a client we could also talk about proxy in other languages, to our server since we have established a connection cnx.

ctx, cancel := context.WithTimeout(context.Background(), time.Second)

Allows to set up a Timeout if our processing in our main context, in our case, our func main passes the second. If this exceeds a DeadlineExceed error, the current call will stop. You can simply check this by setting time.Microsecond instead of time.Second.

defer cnx.Close()

Close the connection after the end of processing. A keyword in the GO defer language is used here to predict the instructions to be performed when you exit the func and GO will take over the instruction(s).

Using the Go client

.\ClientGoDemo01.exe -action TABLE -Multiplicand 5 -Multiplier 10

This command, after compiling both client and server parts. After starting the server part and it is listening, which is executed in command line whatever shell. Lets us ask the server to return the 5 multiplication table, from 0 to 10 (all our childhood multiplication tables!!). The output result will be:

Client started
Table de multiplation de 5 X 10.
5 X 0 = 0
5 X 1 = 5
5 X 2 = 10
5 X 3 = 15
5 X 4 = 20
5 X 5 = 25
5 X 6 = 30
5 X 7 = 35
5 X 8 = 40
5 X 9 = 45
5 X 10 = 50
Client ended.

If you need help on the command line just type the following command:

.\ClientGoDemo01.exe --help

In summary

Here we have just seen:

  • opening the client connection;
  • the instantiation of a proxy;
  • the call of a method to the server which for the client is transparent;
  • the implementation of a timeout on the execution time of the order;
  • closing the connection.

Conclusion

Here, a basic example of setting up a gRPC server and its consumption through a client Using the IDL for the buffers protocol to generate the service, the messages, the service contract.

References

Project Source on GitHub

Here are some references on the subject gRPC and Protocol Buffers from Google.

gRPC Official Site

Protocol Buffers Official Site

Transpilator GitHub

GitHub from Google’s extension to transpiler in GO language


Tags

#Framework#protocol#grpc#rpc
Frédéric Schmidt

Frédéric Schmidt

Software Architect

I'm Software Developer & Architect. I'm more than 20 years experiences in differents IT service companies and software editors. I like studies some new technologies and share this passion altroughts my technical blog.

Expertise

Architecture
Development
Modelisation
Technical writer

Social Media

githublinkedin

Related Posts

gRPC - Présentation
Software Architecture
gRPC - Présentation
July 12, 2020
3 min
© 2022, All Rights Reserved.

Quick Links

Contact Us

About me

Social Media