Introduction to gRPC with Golang

Kittapa S
Touch Technologies
Published in
7 min readJul 7, 2021

gRPC was first developed by Google in 2015 where RPC stands for Remote Procedure Call. Before getting to know gRPC, we have to know what RPC is first.

What is RPC?

RPC is a protocol that helps a program request a service from another program that might be located on a different computer under the same network. It is a form of client-server communication that uses the function call instead of the usual HTTP call. The client requests service and the server provides the service back. It uses Interface Definition Language (IDL) to communicate.

What is “g” in gRPC?

Many people think that “g” stands for Google; however, for each version of gRPC, “g” has different meanings. For example, good, green, gentle, gorgeous, goofy, etc.

Why is gRPC so popular?

The reason that gRPC is so popular is that it is supported by many programming languages and it is easier since HTTP calls are often confusing. With HTTP calls, you have to specify the method like GET, POST, PUT, or DELETE before performing each actions.

In Microservices Architecture, gRPC is very popular due to its versatility. gRPC’s libraries support many languages and thus work well with services that comprise of more than one language.

gRPC Architecture

We all have been using HTTP for a long time; the current one is HTTP/2. Google also created HTTP/2 in 2015 to be used by gRPC.

HTTP/1.1 vs HTTP/2

HTTP or Hyper Text Transfer Protocol is the standard communication protocol for the World Wide Web. Using this protocol, the client sends text based request with methods like GET or POST and the server can response resources back like HTML page.

What makes HTTP/2 different from the traditional HTTP? The new layer, binary, was added to HTTP/2. In this layer, the request and response are broken down into packets called frames. HTTP/2 allows multiple requests or responses to be sent or received together in a single connection. Unlike HTTP/1.1, HTTP/2 allows you to download web files asynchronous from one server. Therefore, HTTP/2 reduces additional round trip time (RTT), making the website load faster.

Header Compression

HTTP/2 has a strategy called HPack to handle when the headers are bigger than its payload. HTTP/2 will encode everything including headers before sending.

Moreover, the protocol will map the header on both the client and the server side. So, if the header contains a different value from the previous header, only the new value will be sent. This function contributes immensely to improving the performance of HTTP/2.

Request#2 will only send the path since it’s the only difference from the previous header.

Protocol Buffer (Protobuf)

Protobuf is where you store your data. Its functions contract in the form of a proto file. It is the most commonly used IDL for gRPC. Below is how the form of the contract looks like.

message Student{
string name = 1;
int64 studentID = 2;
}

Both the client and the server need to have the same proto file. The file acts as the intermediary contract for the client to call any available function from the server.

Metadata

gRPC uses metadata instead of the usual HTTP request header. Metadata is a type of key-value data that can be set by the client or the server side. It is an additional data that might be useful during the communication process. Metadata could be authentication tokens, tags, or any data that is not the actual application data.

Steaming

With gRPC, the ability to send many things in a single connection is possible. Here are three types of streaming in gRPC:

  1. Server Streaming RPC: A good example of this is when a client requests for a homepage that has multiple items and the server responses back separately; enabling the client to use lazy loading.
  2. Client Streaming RPC: The example is when the client uploads a zip/chunk file.
  3. Bidirectional Streaming RPC: This is when both the client and the server send messages to each other without waiting for the response.

What else does gRPC offer us?

  • Load Balancing: gRPC supports a method of load balancing by the client. It can be implemented using the Golang library.
  • Interceptors: Intercept messages can be modified; requests and responses can be modified before sending. The function can also be manipulated by adding additional logging to track response time.
  • Call Cancellation: The client can cancel a gRPC call when the response is not needed anymore. However, this rollback cannot be done on the server side.

Let’s get started with an easy example!

In this example, the client will request a student ID from the server using gRPC and Golang.

You can clone https://github.com/proudkittapa/kafkaExample.git to follow along.

  1. I have created a directory called “gRPCexample” and inside there are three directories: student, client, and server.
  2. I have also created a proto file called “student.proto” in the directory “student”.
syntax = "proto3";

option go_package = "/";
package student;

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

// The response message contains the ID
message ReplyID {
int64 ID = 1;
}
service StudentID {
// Send a name to ask for ID
rpc StudentID (Request) returns (ReplyID) {}

}

In this file, the request contains a name and the response contains an ID. The service “StudentID” will send a request and return it with ID.

3. After creating the proto file, you have to compile the proto file to code using the buffer compiler “protoc” with gRPC Go plugin. To do so, run the following command in the directory “gRPCexample”.

> protoc --go_out=plugins=grpc:student student/student.proto

Now, you will see the file “student.pb.go” in the same directory as student.proto.

4. Now create a gRPC server file in the “server” directory. I named the file “server.go”

package main

import (
"context"
pb "gRPC/student"
"google.golang.org/grpc"
"log"
"math/rand"
"net"
)

const (
port = ":50051"
)

// server is used to implement student.StudentID
type server struct {
pb.UnimplementedGreeterServer
}

// StudentID implements student.StudentID
func (s *server) StudentID(ctx context.Context, in *pb.Request) (*pb.ReplyID, error) {
log.Printf("Received: %v", in)
id := rand.Int63() //generate random ID
reply := &pb.ReplyID{ID: id}
return reply, nil //return reply which contains ID
}

func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}

}

5. Create the file “client.go” in the “client” directory

package main

import (
"context"
pb "gRPC/student"
"google.golang.org/grpc"
"log"
"os"
"time"
)

const (
address = "localhost:50051"
defaultName = "Student1"
)

func main() {
// Set up a connection to the server.
conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)

// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
//request ID
r, err := c.StudentID(ctx, &pb.Request{Name: name})
if err != nil {
log.Fatalf("could not get ID: %v", err)
}
log.Printf("Student: %v, ID: %v",name, r.ID)
}

The client and server will communicate via “localhost:50051”.

6. Now, run “server.go” then “client.go” in a separate terminal.

> go run server/server.go> go run client/client.go

In the terminal where you run server.go, you will see:

Meanwhile, in the terminal where you run client.go, you will receive the ID that’s randomly generated by the server.

Yay, that’s it! You can try running the client once more and see that the ID is now different.

Conclusion

Now, you might wonder whether you should get started with gRPC. The answer is why not when big companies like Netflix, 9GAG, and Microsoft, use gRPC. I guarantee that it is worth trying.

Thank you for your kind patience reading up till here! I hope you all have a better understanding of gRPC. You can also play around using the example above and let me know if you have any problems.

--

--