Más contenido relacionado


Build microservice with gRPC in golang

  1. Build microserviceBuild microservice with gRPC in Golangwith gRPC in Golang David Chou
  2. We are UmboWe are Umbo Computer VisionComputer Vision We buildWe build autonomous videoautonomous video security systemsecurity system
  3. CyberlinkCyberlink TrendMicroTrendMicro Umbo CVUmbo CV Google I/O ExtendGoogle I/O Extend Golang TaipeiGolang Taipei   
  4. A high performance, open source, general purpose standards-based, feature-rich RPC framework.
  5. O(10^10) RPCs per second at Google
  6. gRPC: MotivationgRPC: Motivation Google has its internal RPC called Stubby All applications and systems built using RPCs Over 10^10 RPCs per second Tightly couple with internal infrastructure Not suitable for open source community
  7. gRPC: StatusgRPC: Status A high performance, universal RPC framework Google open sourced it in Feb 2015 Being 1.0 in Aug 2016 Latest version: v1.3.2 Already been adpoted in CoreOS, Netflix, Square, Cisco, Juniper
  8. gRPC: FeaturesgRPC: Features Bi-directional streaming over HTTP/2 Support multi-language, multi-platform Simple service definition framework
  9. Bi-directional streaming over HTTP/2Bi-directional streaming over HTTP/2 Single TCP connection for each client-server pair Support bi-directional streaming
  10. Support multi-language,Support multi-language, multi-platformmulti-platform Use protoc as the code generator Native implementations in C/C++, Java, and Go C stack wrapped by C#, Node, ObjC, Python, Ruby, PHP Platforms supported: Linux, MacOS, Windows, Android, iOS Currently, no browser side support. #8682 gRPC gateway gRPC-web
  11. Simple service definition frameworkSimple service definition framework Use Protocol Buffer IDL Service definition Generate server and client stub code Message definition Binary format Much better performace than json
  12. syntax = "proto3"; package pb; message EchoMessage { string msg = 1; } service EchoService { rpc Echo(EchoMessage) returns (EchoMessage); } Protobuf IDL: EchoServiceProtobuf IDL: EchoService
  13. BenchmarkToJSON_1000_Director-2 500 2512808 ns/op 560427 B/op 9682 allocs/op BenchmarkToPB_1000_Director-2 2000 1338410 ns/op 196743 B/op 3052 allocs/op BenchmarkToJSONUnmarshal_1000_Director-4 1000 1279297 ns/op 403746 B/op 5144 allocs/op BenchmarkToPBUnmarshal_1000_Director-4 3000 489585 ns/op 202256 B/op 5522 allocs/op Json vs Protobuf performanceJson vs Protobuf performance Ref: Dgraph: JSON vs. Binary clients Marshalling: 2x faster, 65% less memory Unmarshalling: 2.6x faster, 50% less memory
  14. Example: DemoServiceExample: DemoService
  15. gRPC Service DefinitiongRPC Service Definition message Demo { string value = 1; } service DemoService { rpc SimpleRPC(Demo) returns (Demo); rpc ServerStream(Demo) returns (stream Demo); rpc ClientStream(stream Demo) returns (Demo); rpc Bidirectional(stream Demo) returns (stream Demo); }
  16. gRPC Service DefinitiongRPC Service Definition gRPC supprots 4 kinds of service methods Unary RPC Server streaming RPC Client streaming RPC Bidirectional RPC
  17. Generate client and server codeGenerate client and server code Run protoc to generate client/server interfaces $ protoc --go_out=plugins=grpc:. demo.proto protoc will generate demo.pb.go Install relevant tools
  18. demo.pb.godemo.pb.go type Demo struct { Value string `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"` } // Client API for DemoService service type DemoServiceClient interface { SimpleRPC(ctx context.Context, in *Demo, opts ...grpc.CallOption) (*Demo, error) ServerStream(ctx context.Context, in *Demo, opts ...grpc.CallOption) (DemoService_ServerStreamClient, ClientStream(ctx context.Context, opts ...grpc.CallOption) (DemoService_ClientStreamClient, error) Bidirectional(ctx context.Context, opts ...grpc.CallOption) (DemoService_BidirectionalClient, error) } // Implementation of DemoService client type demoServiceClient struct { cc *grpc.ClientConn } func NewDemoServiceClient(cc *grpc.ClientConn) DemoServiceClient { ... } // Server API for DemoService service type DemoServiceServer interface { SimpleRPC(context.Context, *Demo) (*Demo, error) ServerStream(*Demo, DemoService_ServerStreamServer) error ClientStream(DemoService_ClientStreamServer) error Bidirectional(DemoService_BidirectionalServer) error }
  19. Go ServerGo Server type server struct{} func (this *server) SimpleRPC(c context.Context, msg *Demo) (*Demo, error) { msg.Value = "Hello" + msg.Value return msg, nil } func (this *server) ServerStream(msg *Demo, stream DemoService_ServerStreamServer) error { for i := 0; i < 10; i++ { err := stream.Send(&Demo{value: "Hello"}) if err != nil { fmt.Printf("err: %sn", err.Error()) } time.Sleep(100 * time.Millisecond) } return nil } func main() { lis, err := net.Listen("tcp", "localhost:12345") if err != nil { log.Fatalf("Failed to listen: %v", err) } grpcServer := grpc.NewServer() RegisterDemoServiceServer(grpcServer, &server{}) grpcServer.Serve(lis) }
  20. Go Client: SimpleRPCGo Client: SimpleRPC func main() { grpcAddr := "localhost:12345" conn, err := grpc.Dial(grpcAddr) if err != nil { log.Fatalf("Dial(%s) = %v", grpcAddr, err) } defer conn.Close() client := NewDemoServiceClient(conn) msg := &Demo{value: "World"} reply, err := client.SimpleRPC(context.Background(), msg) if err != nil { log.Fatalf("SimpleRPC(%#v) failed with %v", msg, err) } println("received message " + reply.Value) }
  21. Go Client: ServerStreamGo Client: ServerStream func main() { grpcAddr := "localhost:12345" conn, err := grpc.Dial(grpcAddr) if err != nil { log.Fatalf("Dial(%s) = %v", grpcAddr, err) } defer conn.Close() client := NewDemoServiceClient(conn) stream, err := client.ServerStream(context.TODO(), &Demo{ Value: "Hello", }) for { msg, err := stream.Recv() if err == io.EOF { break } fmt.Printf("%+vn", msg) } }
  22. Let's go deeperLet's go deeper
  23. gRPC build-in authenticationgRPC build-in authentication Two types of Credentials objects Channel credentials Call credentials
  24. Channel credentialsChannel credentials Credentials are attached to a Channel Ex: SSL credentials tls := credentials.NewClientTLSFromCert(nil, "") conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(tls)) creds, err := credentials.NewServerTLSFromFile(certFile, keyFile) server := grpc.NewServer(grpc.Creds(creds)) server.Serve() TLS on server side TLS on client side
  25. Call credentialsCall credentials Credentials are attached to each RPC call Token based authentication, ex: OAuth, JWT
  26. func unaryInterceptor(ctx context.Context, req interface{} if err := authorize(ctx); err != nil { return err } return handler(ctx, req) } func authorize(ctx context.Context) error { if md, ok := metadata.FromContext(ctx); ok { if checkJWT(md["jwt"][0]) { return nil } return AccessDeniedErr } return EmptyMetadataErr } grpc.NewServer(grpc.UnaryInterceptor(unaryInterceptor)) TLS on server side type JWTCreds struct { Token string } func (c *JWTCreds) GetRequestMetadata(context.Context, .. return map[string]string{ "jwt": c.Token, }, nil } grpc.Dial(target, grpc.WithPerRPCCredentials(&JWTCreds{ Token: "test-jwt-token", })) TLS on client side Ref: grpc-go #106
  27. gRPC load balancegRPC load balance Approaches to Load Balancing Server-side LB Client-side LB
  28. Load Balancing in gRPCLoad Balancing in gRPC #gRPC load balancing proposal
  29. Any Question?Any Question?