gRPC Tutorial

gRPC (Remote Procedure Calls) is an open source remote procedure call (RPC) system initially developed at Google. It uses HTTP/2 for transport, Protocol Buffers as the interface description language, and provides features such as authentication, bidirectional streaming and flow control, blocking or nonblocking bindings, and cancellation and timeouts. It generates cross-platform client and server bindings for many languages. Most common usage scenarios includes connecting services in microservices style architecture and connect mobile devices, browser clients to backend services

Getting Started with gRPC

The workflow to create a gRPC service is simple:

  • Create the service definition and payload structure in the Protocol Buffer (.proto) file.
  • Generate the gRPC code from the .proto file using proto compiler.
  • Implement the server in one of the supported languages.
  • Create the client that invokes the service through the Stub.
  • Run the server and client(s).

Set up Environment for gRPC

Configure Python

python -m pip install virtualenv
virtualenv venv
source venv/bin/activate
python -m pip install --upgrade pip

Install gRPC and gRPC Tools

python -m pip install grpcio
python -m pip install grpcio-tools
npm install grpc --global

Create the directories for the Protocol Buffer, Server, and Client

mkdir Proto
mkdir Server
mkdir -p Client/Python

Create the Protocol Buffer (Proto/Calc.proto) in the Proto directory

syntax = "proto3";

package calc;

service Calculator {

rpc Add (AddRequest) returns (AddReply) {}
rpc Substract (SubstractRequest) returns (SubstractReply) {}
rpc Multiply (MultiplyRequest) returns (MultiplyReply) {}
rpc Divide (DivideRequest) returns (DivideReply) {}
rpc SquareRoot (SquareRootRequest) returns (SquareRootReply) {}
}

message SquareRootRequest {
    float n1= 1;
}

message SquareRootReply {
    float n1= 1;
}


message AddRequest{

int32 n1=1;
int32 n2=2;
}

message AddReply{

int32 n1=1;
}

message SubstractRequest{

int32 n1=1;
int32 n2=2;
}

message SubstractReply{

int32 n1=1;
}

message MultiplyRequest{

int32 n1=1;
int32 n2=2;
}

message MultiplyReply{

int32 n1=1;
}

message DivideRequest{

int32 n1=1;
int32 n2=2;
}

message DivideReply{

float f1=1;
}

Generate Python client and server code and copy it to the directories

python -m grpc.tools.protoc  --python_out=. --grpc_python_out=. --proto_path=. Calc.proto
cp Calc_pb2.py Calc_pb2_grpc.py ../Server
cp Calc_pb2.py Calc_pb2_grpc.py ../Client/Python

Create the Server (Server/Calc_Server.py)

from concurrent import futures
import time

import grpc
import math

import Calc_pb2
import Calc_pb2_grpc

_ONE_DAY_IN_SECONDS = 60 * 60 * 24

class Calculator(Calc_pb2_grpc.CalculatorServicer):

 def Add(self, request, context):
   return Calc_pb2.AddReply(n1=request.n1+request.n2)

 def Substract(self, request, context):
   return Calc_pb2.SubstractReply(n1=request.n1-request.n2)

 def Multiply(self, request, context):
   return Calc_pb2.MultiplyReply(n1=request.n1*request.n2)

 def Divide(self, request, context):
   return Calc_pb2.DivideReply(f1=request.n1/request.n2)

 def SquareRoot(self, request, context):return Calc_pb2.SquareRootReply(y = math.sqrt(request.n1))

def serve():
 server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
 Calc_pb2_grpc.add_CalculatorServicer_to_server(Calculator(), server)
 server.add_insecure_port('[::]:50050')
 server.start()
 try:
   while True:
     time.sleep(_ONE_DAY_IN_SECONDS)
 except KeyboardInterrupt:
   server.stop(0)

if __name__ == '__main__':
 serve()

Launch the Server

python Calc_Server.py

Create the Python Client (Client/Python/Calc_Client.py)

from __future__ import print_function

import grpc

import Calc_pb2
import Calc_pb2_grpc

def run():
 channel = grpc.insecure_channel('localhost:50050')
 stub = Calc_pb2_grpc.CalculatorStub(channel)
 response = stub.Add(Calc_pb2.AddRequest(n1=50,n2=50))
 print("Addition = " + str(response.n1))
 response = stub.Substract(Calc_pb2.SubstractRequest(n1=200,n2=10))
 print("Substraction = " + str(response.n1))
 response = stub.Multiply(Calc_pb2.MultiplyRequest(n1=10,n2=10))
 print("Multiplication = " + str(response.n1))
 response = stub.Divide(Calc_pb2.DivideRequest(n1=200,n2=10))
 print("Devide = " + str(response.f1))
 response = stub.SquareRoot(Calc_pb2.SquareRootRequest(n1=100))
 print("SquareRoot = " + str(response.y))


if __name__ == '__main__':
  run()

Launch the Python Client

python Calc_Client.py

#output
Addition = 100
Substraction = 190
Multiplication = 100
Devide = 20
SquareRoot = 10

Reference

https://thenewstack.io/grpc-lean-mean-communication-protocol-microservices

https://engineering.semantics3.com/a-simplified-guide-to-grpc-in-python-6c4e25f0c506

Leave a Reply

Your email address will not be published. Required fields are marked *

LACONIQ INFOTECH PRIVATE LIMITED is a Pune based company working towards excellence in the contract staffing service

Company

© 2022 Laconiq Infotech. All Rights Reserved