Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building reliable and efficient services throug...

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.

Gustavo Pantuza

September 21, 2019
Tweet

More Decks by Gustavo Pantuza

Other Decks in Programming

Transcript

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

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

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

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

    to build a simple distributed systems tool My personal opinion
  5. Who is using? "We’ve also seen a squishing and a

    narrowing of our latency windows" https://www.cncf.io/netflix-case-study/
  6. Who is using? "distribution layer is the first layer to

    communicate with other nodes" https://www.cockroachlabs.com/docs/stable/architecture/distribution-layer.html
  7. 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
  8. 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
  9. 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
  10. $> # Install gRPC libraries $> zypper install protobuf-devel $>

    apt install protobuf-compiler $> brew install protobuf Install gRPC dependencies gRPC Workflow
  11. 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
  12. $> # One new file generated: $> # . cheese.pb.go

    $> # Protocol Buffer message $> # and gRPC code $> ls cheese.proto cheese.pb.go Compilation Results gRPC Workflow
  13. 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
  14. 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
  15. 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
  16. 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()) } }
  17. 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
  18. gRPC Design Server streaming // From Server to Client rpc

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

    Upload(stream chunks) returns (Done) {}
  20. 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
  21. gRPC Design Pluggable Large distributed systems need: • Security •

    Health-checking • Load-balancing • Failover • Monitoring • Tracing • logging Golang Interceptor example
  22. 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
  23. 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))
  24. 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) )
  25. gRPC References • Official project site • Official project Repositories

    • Awesome gRPC project • Official examples for other languages • Protocol Buffer official site
  26. 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