gRPC Quickstart using Golang

What is gRPC?

gRPC is a modern open source high performance 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.

source: grpc.io

Prerequisites

go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2

Make sure the GOPATH/bin is part of your PATH env

export PATH="$PATH:$(go env GOPATH)/bin"

Now, we are ready to get started.

Steps

  • Setup Projects

  • Create gRPC server

    • Generate proto spec file
  • Create gRPC client

  • Test RPCs

Setup Projects

To keep things simple, lets create two projects

  • Server

  • Client

Add simple main.go files in each and initialize go module (ex - go mod init github.com/mridulganga/server), also make sure to add them in GOPATH as client would need to import a file exposed by the server.

Create gRPC server

Generate proto spec file

Create a new file called helloworld.proto in server project's pkg/helloworld folder

syntax = "proto3";

option go_package = "github.com/mridulganga/server/pkg/helloworld";
package helloworld;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

Now cd to the folder and run the following command to generate the protobuf and gRPC interface

cd server/pkg/helloworld
protoc --go_out=. --go_opt=paths=source_relative \
    --go-grpc_out=. --go-grpc_opt=paths=source_relative \
    helloworld.proto

The above step should generate two files in the same folder

  • helloworld.pb.go

  • helloworld_grpc.pb.go

Create the server in main.go (server/main.go)

package main

import (
    "context"
    "flag"
    "fmt"
    "log"
    "net"

    "google.golang.org/grpc"
    pb "github.com/mridulganga/server/pkg/helloworld"
)

var (
    port = flag.Int("port", 50051, "The server port")
)

// 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() {
    flag.Parse()
    lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    log.Printf("server listening at %v", lis.Addr())
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

Code taken from https://github.com/grpc/grpc-go/blob/master/examples/helloworld/greeter_server/main.go

Create gRPC client

Create the client in main.go (client/main.go)

package main

import (
    "context"
    "flag"
    "log"
    "time"

    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    pb "github.com/mridulganga/server/pkg/helloworld"
)

const (
    defaultName = "world"
)

var (
    addr = flag.String("addr", "localhost:50051", "the address to connect to")
    name = flag.String("name", defaultName, "Name to greet")
)

func main() {
    flag.Parse()
    // Set up a connection to the server.
    conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
    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.
    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())
}

code taken from https://github.com/grpc/grpc-go/blob/master/examples/helloworld/greeter_client/main.go

Test RPC

Run the server

go run server/main.go &

Note that we are using & to run server in background, alternatively you can open a new terminal for running the client

Run the client

go run client/main.go
go run client/main.go -name mridul

The client should log "Greeting world" or the name which is supplied. The client is using gRPC to connect to the server and call SayHello method on the server.