Building reliable and efficient services through gRPC

Building reliable and efficient services through gRPC

Slides for a presentation that describes gRPC as a tool for building reliable and efficient distributed system. The talk shares what exactly is gRPC, its background, which companies are using it and their cases. Also, shares how is the gRPC development workflow through a basic example of service implemented with it. After the example is shown the gRPC internal design, features and security. At the end, a demo and many references links are presented as well.

B1412c9ed55333c1df561f64dfad69d3?s=128

Gustavo Pantuza

September 21, 2019
Tweet

Transcript

  1. Gustavo Pantuza Building reliable and efficient services through gRPC

  2. Agenda • What is gRPC? • Background • Who is

    using • gRPC Workflow • gRPC Design • Security • Demo • References
  3. What is gRPC? "A high performance, open-source universal RPC framework"

    Project site: https://grpc.io Github: https://github.com/grpc
  4. What is gRPC? • Remote Procedure Call • Type Safe

    • Polyglot • Binary message format • Multiplexed connections
  5. What is gRPC? A bunch of best practices gathered together

    to build a simple distributed systems tool My personal opinion
  6. What is gRPC?

  7. Background • General-purpose RPC infrastructure called Stubby Open Source

  8. Background Connect the large number of microservices running within and

    across our data centers
  9. Background Cloud Native Computing Foundation To Host gRPC from Google

  10. Who is using? "We’ve also seen a squishing and a

    narrowing of our latency windows" https://www.cncf.io/netflix-case-study/
  11. Who is using? "Implementing GRPC/Telemetry on XR devices" https://community.cisco.com/t5/service-providers-documents/implementing-grpc-telemetry-on-xr-devices/ta-p/3393966

  12. Who is using? "distribution layer is the first layer to

    communicate with other nodes" https://www.cockroachlabs.com/docs/stable/architecture/distribution-layer.html
  13. Who is using? "more compact and efficiently serializable RPC payload"

    https://cilium.io/blog/grpc/
  14. Who is using? "layers the best features of IDL-specified RPC

    onto a standard" https://linkerd.io/2017/01/11/http2-grpc-and-linkerd/#_ga=2.36853351.619173598.1561427300-69268088.1561427300
  15. Who is using? https://stackshare.io/grpc

  16. gRPC Workflow • The Message Protocol

  17. gRPC Workflow • The Message Protocol Message definition protoc Compiler

    Python Go C++
  18. syntax = "proto3"; package cheesefarm; Define the version and the

    package gRPC Workflow
  19. syntax = "proto3"; package cheesefarm; message Cheese { int32 age

    = 1; CheeseType type = 2; } enum CheeseType { EMMENTAL = 0; BRIE = 1; PECORINO = 2; ROQUEFORT = 3; CANASTRA = 4; } message CheeseRequest { CheeseType type = 1; } Create your messages gRPC Workflow
  20. syntax = "proto3"; package cheesefarm; message Cheese { int32 age

    = 1; CheeseType type = 2; } enum CheeseType { EMMENTAL = 0; BRIE = 1; PECORINO = 2; ROQUEFORT = 3; CANASTRA = 4; } message CheeseRequest { CheeseType type = 1; } service CheeseService { rpc Order(CheeseRequest) returns (Cheese); } Describe your Service interface gRPC Workflow
  21. $> # Install gRPC libraries $> zypper install protobuf-devel $>

    apt install protobuf-compiler $> brew install protobuf Install gRPC dependencies gRPC Workflow
  22. gRPC Design $> # Compile only messages with Golang $>

    # as target in the current directory $> protoc --go_out=. cheese.proto $> # Compile messages and services with Golang $> # as target in the current directory $> protoc --go_out=plugins=grpc:. cheese.proto Compilation time
  23. $> # One new file generated: $> # . cheese.pb.go

    $> # Protocol Buffer message $> # and gRPC code $> ls cheese.proto cheese.pb.go Compilation Results gRPC Workflow
  24. Resulted code example gRPC Workflow // protoc resulted file: cheese.pb.go

    // Code generated by protoc-gen-go. DO NOT EDIT. // source: cheese.proto package cheesefarm import ( context "context" fmt "fmt" proto "github.com/golang/protobuf/proto" grpc "google.golang.org/grpc" math "math" ) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package type CheeseType int32
  25. package main import ( "fmt" "log" "net" "os" "path/filepath" "google.golang.org/grpc"

    "google.golang.org/grpc/credentials" pb "github.com/pantuza/grpc/cheese" ) func main() { wd, _ := os.Getwd() certFile := filepath.Join(wd, "ssl", "cert.pem") keyFile := filepath.Join(wd, "ssl", "private.key") creds, _ := credentials.NewServerTLSFromFile(certFile, keyFile) serverAddr := fmt.Sprintf("%s:%d", pb.ADDR, pb.PORT) listen, err := net.Listen("tcp", serverAddr) if err != nil { log.Fatalf("Failed to listen: %v", err) } grpcServer := grpc.NewServer(grpc.Creds(creds)) pb.RegisterCheeseServiceServer(grpcServer, pb.NewServer()) fmt.Printf("Listening gRPC on %s\n", serverAddr) grpcServer.Serve(listen) } Server Implementation gRPC Workflow
  26. package cheesefarm import ( "context" "fmt" "time" "math/rand" ) const

    ( ADDR string = "localhost" PORT int = 4000 ) type CheeseServer struct { } func NewServer() *CheeseServer { rand.Seed(time.Now().UnixNano()) server := &CheeseServer{} return server } func (s *CheeseServer) Order(ctx context.Context, r *CheeseRequest) (*Cheese, error) { time.Sleep(time.Duration(rand.Intn(3))*time.Second) fmt.Printf("[gRPC] Order=%s\n", r.GetType()) cheese := &Cheese{} cheese.Age = 10 cheese.Type = r.GetType() return cheese, nil } Service Implementation gRPC Workflow
  27. Client Implementation gRPC Workflow package main import ( ... "google.golang.org/grpc"

    "google.golang.org/grpc/credentials" pb "github.com/pantuza/grpc/cheese" ) func main() { rand.Seed(time.Now().UnixNano()) wd, _ := os.Getwd() certFile := filepath.Join(wd, "ssl", "cert.pem") creds, err := credentials.NewClientTLSFromFile(certFile, "") if err != nil { log.Fatal("Error: %v", err) } serverAddr := fmt.Sprintf("%s:%d", pb.ADDR, pb.PORT) conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(creds)) if err != nil { log.Fatal("Fail to dial: %v", err) } defer conn.Close() client := pb.NewCheeseServiceClient(conn) ctx := context.Background() for { order := &pb.CheeseRequest{Type: pb.CheeseType(rand.Intn(100) % 5)} cheese, err := client.Order(ctx, order) if err != nil { log.Fatal("Error: %v", err) } fmt.Printf("[gRPC] Received=%s\n", cheese.GetType()) } }
  28. gRPC Design Http/2 by design • Binary payload • Multiplexed

    connections • Extensible
  29. gRPC Design Streaming // From Server to Client rpc ListFeatures(Rectangle)

    returns (stream Feature) {} // From Client to Server rpc RecordRoute(stream Point) returns (RouteSummary) {} // Bidirectional rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} The classic pair Send() and Recv() from socket library
  30. gRPC Design Server streaming // From Server to Client rpc

    Watch(Match) returns (stream Video) {}
  31. gRPC Design Client streaming // From client to Client rpc

    Upload(stream chunks) returns (Done) {}
  32. syntax = "proto3"; package stream; message Match { string id

    = 1; } message Video { bytes data = 1; string data_type = 2; string data_shape = 3; } service Soccer { rpc Watch (Match) returns (stream Video) {} } Protocol Buffer Example
  33. gRPC Design Bidirectional streaming // Bidirectional rpc Chat(stream video) returns

    (stream video) {}
  34. gRPC Design Blocking & Non-Blocking

  35. gRPC Design Cancellation & Timeout

  36. gRPC Design Pluggable Large distributed systems need: • Security •

    Health-checking • Load-balancing • Failover • Monitoring • Tracing • logging Golang Interceptor example
  37. gRPC Design Standardized Status Codes CODE NUMBER OK 0 CANCELLED

    1 UNKNOWN 2 INVALID_ARGUMENT 3 ... ... https://github.com/grpc/grpc/blob/master/doc/statuscodes.md
  38. gRPC security Supported and Authentication methods https://grpc.io/docs/guides/auth/

  39. gRPC security TLS On the Server // Loads Certificate and

    private key certFile := filepath.Join(wd, "ssl", "cert.pem") keyFile := filepath.Join(wd, "ssl", "private.key") // Creates the credentials object creds, _ := credentials.NewServerTLSFromFile(certFile, keyFile) // Adds credentials to the gRPC server grpcServer := grpc.NewServer(grpc.Creds(creds))
  40. gRPC security TLS On the Client // Loads client certficate

    certFile := filepath.Join(wd, "ssl", "cert.pem") creds, err := credentials.NewClientTLSFromFile(certFile, "") // Adds certficate on the connection conn, err := grpc.Dial( serverAddr, grpc.WithTransportCredentials(creds) )
  41. Demo The Cheese SECURE Service

  42. gRPC References • Official project site • Official project Repositories

    • Awesome gRPC project • Official examples for other languages • Protocol Buffer official site
  43. gRPC Golang Examples • A simplified guide to gRPC in

    Golang • gRPC Basics - Golang • Python Quick Start • Python gRPC official example • A brief introduction to gRPC in Go
  44. Cheese Farm example https://github.com/pantuza/grpc-golang-examples

  45. Hey developers, please, play with me <3

  46. Questions? Comments? https://blog.pantuza.com https://github.com/pantuza https://twitter.com/gpantuza gifts