# gRPC, Performant, Easy and less JSON ### Kevin Collas-Arundell #### [@kcollasarundell](https://twitter.com/) #### 01 Apr 2019

Let’s Talk about REST

  • Easy to reason about
  • Text based protocol
  • "Simple" to implement
  • Slow to encode
  • No support for streaming
  • No concurrency
  • Every client is slightly different
  • Optimistic documentation
  • Easy to inspect
  • And yet another client to write

But Swagger OpenAPI

  • Optimistic accuracy
  • Disconnected from implementation and release
  • Not mandatory
  • Still JSON
  • Hard to implement compatible changes

What is gRPC

Wtf is protocol buffers (protobuf)

  • Binary message format
  • Default wire format for gRPC
  • One of several supported formats
  • Faster than JSON but you can find faster formats
  • Generated interface
  • Wide language support
  • No JSON


syntax = "proto3"; 

option java_multiple_files = true;
option java_package = "io.protobuf.examples.helloworld";
option java_outer_classname = "HelloWorldProto"; 

package helloworld; 

message HelloRequest {
    string name = 1;
    string colour = 2;
}

message HelloReply {
    string message = 1;
    bool authed = 2;
}
    
Protobuf message format Copyright Martin Kleppman

Most importantly

The G stands for

  • 1.0 ‘g’ stands for ‘gRPC’
  • 1.1 ‘g’ stands for ‘good’
  • 1.2 ‘g’ stands for ‘green’
  • 1.3 ‘g’ stands for ‘gentle’
  • 1.4 ‘g’ stands for ‘gregarious’
  • 1.18 ‘g’ stands for ‘goose’
  • 1.19 ‘g’ stands for ‘gold’
  • 1.20 ‘g’ stands for ‘godric’

gRPC

  • Many language implementations
  • HTTP2
  • Generated stubs
  • Strongly typed and validated
  • Bidirectional streaming
  • No JSON
  • Reflection implementation for auto discovery
  • Generated stubs
  • Standard middleware patterns
  • Not having to write yet another client

The Proto Spec



syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";

package helloworld;

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

message HelloRequest {
  string name = 1;
  string colour = 2;
}

message HelloReply {
  string message = 1;
  bool authed = 2;
}
    

Building the stubs



protoc -I helloworld/ helloworld/helloworld.proto \
--go_out=plugins=grpc:helloworld
    

The interface



type GreeterServer interface {
    SayHello(context.Context, *HelloRequest) (*HelloReply, error)
}

func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) {
    s.RegisterService(&_Greeter_serviceDesc, srv)
}
    

Building a server



type server struct{}

func (s *server) SayHello(
        ctx context.Context,
        in *pb.HelloRequest,
    ) (*pb.HelloReply, error) {
    log.Printf("Received: %v", in.Name)
    return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}
    


func main() {
    lis, err := net.Listen("tcp", 8080)
    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)
    }
}
    

And now a client



    conn, _ := grpc.Dial(address, grpc.WithInsecure())
    c := pb.NewGreeterClient(conn)
    r, err := c.SayHello(ctx, &pb.HelloRequest{
        Name: "Bob",
    })
    fmt.Println(r.Message)
    

BORING

Time to tempt fate

TODO: Add Asciinema recordings

gRPC downsides

  • Load Balancing -> http2 is still not supported by some LBs
  • No direct support for browser clients
  • Breaking API changes
  • Poor documentation for some languages
  • No standardisation across languages

Sources