Microservices, gRPC and Protocol Buffers — Hello World

In the last decade, A huge update in the development and deployment of different web based services has occurred. We have seen a wide variety of projects which moved towards the advanced “Microservice Architecture”, replacing the old traditional “Monolithic Architecture”. This shift of technology has already done wonders for us. As we move towards microservices, we are inclined towards the fact that “distributed in nature and smaller chunks are much easier to handle”, so here we have microservices that can be handled conveniently. For interaction among different microservices the HTTP API calls were being used, which seems great.

From REST to gRPC

About gRPC?

“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.”

Let’s look closely at the concept of remote procedure calls (RPC), In simple words the messages that the server sends to the remote system in order to get execute the the method or the task done. Google’s based RPC is actually designed and developed for the efficient and smooth communication between the services. Few important aspects to remember while looking at the concept of gRPC.

gRPC Architecture diagram, link

HTTP/2: It uses HTTP/2 protocol instead of HTTP 1.1, which allows multiple bidirectional streams that can be created and sent over TCP connections.

Language platforms independent: Two services may be written in different languages, say Python and Golang. gRPC ensures smooth communication between them.

Integrated Auth and load balancing: gRPC provides all these features, making it a secure and reliable option to choose.

Protocol Buffers: It uses protocol buffers for the definition of the type of data, as the message interchange format. It is an open source mechanism for serializing structured data (although it can be used with other data formats such as JSON), which is also developed by google.

Building APIs with gRPC

  • Client: responsible for making the gRPC call to the server.
  • Server: responsible for serving the client requests.
  • Proto file: Proto file comprises the declaration of the service that is used to generate stubs (<package_name>_pb2.py and <package_name>_pb2_grpc.py). It can be understood as a step. We actually don’t need to define it when we are working with HTTP APIs (we use JSON and we forget the rest)
syntax = "proto3";

package grpctest;

service Grpctest{
// A simple RPC.
//
// Obtains the MessageResponse at a given position.
rpc GetServerResponse(Message) returns (MessageResponse) {}

}

message Message{
string message = 1;
}

message MessageResponse{
string message = 1;
bool received = 2;
}

Here we have created a service named Grpctest. In this service we have GetServerResponse() which simply takes an input of type Message and returns a MessageResponse. This .proto file will be now used to generate the stubs using the following command;

$ pip3 install grpcio grpcio-tools (for installing gRPC stuff)$ python3 -m grpc_tools.protoc --proto_path=. ./grpctest.proto --python_out=. --grpc_python_out=.

Two files are generated named grpctest_pb2.py and grpctest_pb2_grpc.py

Writing Client and Server

import grpc
from concurrent import futures
import time
import grpctest.grpctest_pb2_grpc as pb2_grpc
import grpctest.grpctest_pb2 as pb2


class GrpctestService(pb2_grpc.GrpctestServicer):

def __init__(self, *args, **kwargs):
pass

def GetServerResponse(self, request, context):

# get the string from the incoming request
message = request.message
result = f'Hello I am up and running received "{message}" message from you'
result = {'message': result, 'received': True}

return pb2.MessageResponse(**result)


def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
pb2_grpc.add_GrpctestServicer_to_server(GrpctestService(), server)
server.add_insecure_port('[::]:50051')
server.start()
server.wait_for_termination()


if __name__ == '__main__':
serve()

Writing the code for client;

import grpc
import grpctest.grpctest_pb2_grpc as pb2_grpc
import grpctest.grpctest_pb2 as pb2


class grpctestClient(object):
"""
Client for gRPC functionality
"""

def __init__(self):
self.host = 'localhost'
self.server_port = 50051

# instantiate a channel
self.channel = grpc.insecure_channel(
'{}:{}'.format(self.host, self.server_port))

# bind the client and the server
self.stub = pb2_grpc.GrpctestStub(self.channel)

def get_url(self, message):
"""
Client function to call the rpc for GetServerResponse
"""
message = pb2.Message(message=message)
print(f'{message}')
return self.stub.GetServerResponse(message)


if __name__ == '__main__':
client = grpctestClient()
result = client.get_url(message="Hello Server you there?")
print(f'{result}')

Execution of the Server and Client

$ python3 grpctest_server.py$ python3 grpctest_client.py
Running the gRPC server
Running the gRPC client

In a Nutshell

What’s Next

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store