gRPC is a very useful tool to use as a medium for communication or data transfer between services. It has great support for multiple languages and platforms.
What is RPC?
Remote Procedure Call (RPC) is the concept of calling a function on a program from another program, these programs can be running on different machines. REST API is an example of RPC where a client service sends an http request to a server to invoke some logic and get the response.
What is gRPC?
gRPC is a way to do RPC with a set of standards to achieve the data transfer faster and efficient. What makes it high performance is the usage of HTTP/2 as well as Protocol Buffers, which is a binary serialization format.
Protocol Buffers
When transferring data between two programs / services, the data will be serialized and deserialized. Protocol Buffers is a method of serializing structured data. It is language and platform neutral and is extensible. It’s a great way to define the data structure and services.
sequenceDiagram participant Client participant Server Client->>Server: gRPC Call Server->>Server: Process and serialize response Server->>Client: Response Client->>Client: Deserialize and continue
How to implement gRPC? ( golang example )
Prerequisites
- golang
- protobuf tools
- Create a go project and install the gRPC package.
go mod init github.com/adharshmk96/grpc-example
go get -u google.golang.org/grpc
- Create a directory for the service and message types.
mkdir helloworld
touch helloworld/helloworld.proto
- Define the service and message types using Protocol Buffers.
helloworld/helloworld.proto
syntax = "proto3";
package helloworld;
// Specify the Go package where the code will be generated.
option go_package = "../helloworld";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
- Generate the client and server code using the Protocol Buffers compiler.
protoc --go_out=. --go-grpc_out=. helloworld.proto
- Implement the service in the server.
main.go
package main
import (
"context"
"log"
"net"
pb "github.com/adharshmk96/grpc-example/helloworld"
"google.golang.org/grpc"
)
const (
port = ":50051"
)
// server is used to implement helloworld.GreeterServer.
type server struct {
pb.UnimplementedGreeterServer
}
// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("Received: %v", in.GetName())
return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}
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)
}
}
- Create client to call the service.
package main
import (
"context"
"log"
"os"
"time"
pb "github.com/adharshmk96/grpc-example/helloworld"
"google.golang.org/grpc"
)
const (
address = "localhost:50051"
defaultName = "world"
)
func main() {
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)
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
}
gRPC vs REST
gRPC is a great alternative to REST API for microservices and APIs. It has a lot of advantages over REST API:
- Performance: gRPC is faster than REST API because it uses HTTP/2 and Protocol Buffers.
- Language and Platform Neutral: gRPC supports multiple languages and platforms.
- Bidirectional Streaming: gRPC supports bidirectional streaming, which means both client and server can send and receive data at the same time.
- Error Handling: gRPC has better error handling compared to REST API.
- Code Generation: gRPC generates client and server code for multiple languages.
- Security: gRPC has built-in support for authentication and authorization.