What is gRPC ?

gRPC stands for google Remote Procedure Call and it is the technology that will invetably lead the future of API designing and communication

What does RPC mean

RPC stands for Remote Procedure Call and it simply defines the *procedure for calling a function on the server from the client .

Why should you care

Well, it's basically 5 things that gRPC offers out of the box

  1. Speed => as it is transmitted through multiplexing/ over HTTP2 ([Link to blog](http://))
  2. Security => As HTTP2 compulsarily implements SSL
  3. Developer Ease => gRPC is language agnostic so you could literally talk to a python server from a react client, have a C++ proxy in the middle and handle yor database in Java without the heavy lifting of serializing communication objects
    1. There are several more of such features that gRPC hands out of the box for API management

      Resources

      I have committed all the protofiles in detailed branches at this github repository for your perusal

      crew-guy/gRPC
      A repository that explains setting up modern, fast, language agnostic APIs using the gRPC framework - crew-guy/gRPC

      This is the file structure that I have followed while designing this API.

      
      root_folder/
      |-- client/
      |   |-- client.js
      |-- node_modules  
      |-- protos/
      |   |-- max.proto
      |-- server/
           |-- index.js
           |-- protos/
              |-- max_pb.js
              |-- max_grpc_pb.js
      

      0. Sample Problem

      In this exercise, we will be building a Calculate the sum of numbers sent from client to server.

      The function takes a Request message that has 2 integers, and returns a single Response that represents the sum of these numbers.

      1. Make the protofile

      This just involves creation of 3 things

      1. Request
      2. Response
      3. Service (The function that will take in request and return a response)
      syntax="proto3";
      
      package PACKAGENAME;
      
      message SumMessage{
          int32 first_num = 1;
          int32 second_num = 2;
      }
      
      message SumRequest{
          SumMessage sum_message = 1; 
      }
      
      message SumResponse{
          int32 result = 1;
      }
      
      service SumService{
          rpc Sum(SumRequest) returns (SumResponse){}
      }
      

      Here, SumRequest and SumResponse are the request response objects and SumMessage just helps describe the request object

      2. Generate the protofiles

      Packages required : protoc, grpc-tools

      1. grpc-tools

      npm i grpc-tools
      

      We get SumServiceService and SumServiceClient generated from the "grpc-tools" module that will act on our proto to create the client and service (server)

      Output file ⇒ PACKAGENAME_grpc_pb.js

      2. protoc

      Whereas, the protoc will simply generate the Request and Response objects and give us getters and setters on them

      Output filename ⇒ PACKAGENAME_pb.js
      sudo protoc -I=. ./protos/sum.proto \                                        
        --js_out=import_style=commonjs,binary:./server \  
        --grpc_out=./server \
        --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin`
      

      Here the inside the main project directory, we have a client, server and protos subdirectory. Currently, we are generating the API from proto file in the protos directory into the protos subdirectory inside the server directory

      3. Setup a gRPC server

      npm i grpc google-protobuf
      

      Import the necessary dependencies. Here,

      1. sum_pb ⇒  Contains all the details about the request and response object whereas the
      2. sum_grpc_pb ⇒  Will help the grpc server create an API from the proto generated code.
      const grpc = require("grpc")
      const sumService = require('./protos/sum_grpc_pb')
      const sums = require('./protos/sum_pb')
      

      Define the function that will handle the request and return a response. This function is what we defined in the proto file and this is also the function that will be callled from the client

      const sum = (call, callback) =>
      
      // The name is chosen as "sum" as in the proto we have said, in PascalCasing that the "Sum" function will take in a request and return a response
      
      {
          const summing = new sums.SumResponse()
          summing.setResult(
      					call.request.getSumMessage().getFirstNum() 
      				+ call.request.getSumMessage().getSecondNum()
      		)		
          callback(null,summing)
      }
      

      Start up the gRPC server and link it to our function and proto generated code

      const server = new grpc.Server()
       
      server.addService(sumService.SumServiceService,{sum})
      const url = "127.0.0.1:50051"
      server.bind(url, grpc.ServerCredentials.createInsecure())
      server.start()
      

      4. Setup the Client Side

      Import the necessary dependencies.

      1. sum_grpc_pb ⇒ Contains proto generated code that will help us setup the client and link it to the server functions we have defined
      2. sum_pb ⇒ Contains code to help us access and work with the request object
      const grpc = require('grpc');
      const sumService = require('../server/protos/sum_grpc_pb')
      const sums = require('../server/protos/sum_pb')
      

      Setup a client using the proto generated code

      const sumClient = new sumService.SumServiceClient(
          'localhost:50051',
          grpc.credentials.createInsecure()
      )
      

      Configure and send the request object

      const sumRequest = new sums.SumRequest()
      const sumObject = new sums.SumMessage()
      sumObject.setFirstNum(3)
      sumObject.setSecondNum(10)
      sumRequest.setSumMessage(sumObject)
      

      Handle the response received on the client side

      sumClient.sum(sumRequest, (error, response) =>
      {
          if (!error)
          {
              console.log(`Sum result : ${response.getResult()}`)
          } else
          {
              console.log(error)
          }
      })
      

      Add service to server and start it

      //* Setup a server
      const server = new grpc.Server()
      
      server.addService(sumService.SumServiceService, { sum })
      
      //? START THE SERVER
      const URL_ENDPOINT = "127.0.0.1:50051"
      server.bind(URL_ENDPOINT, grpc.ServerCredentials.createInsecure())
      server.start()
      
      console.log(chalk.green(`Server running on ${URL_ENDPOINT}`))
      

      Conclusion

      Congratulations ! You are now equipped with the futuristic skills of bidirectional streaming type API designing. Thanks a lot for reading this blog. If you like more content like this, subscribe to my mailing list

      Conclusion

      Congratulations ! You are now equipped with the futuristic skills of API designing. Thanks a lot for reading this blog. If you like more content like this, subscribe to my mailing list