Build microserviceBuild microservice with gRPC in Golangwith gRPC in Golang David Chou
We are UmboWe are Umbo Computer VisionComputer Vision We buildWe build autonomous videoautonomous video security systemsecurity system
CyberlinkCyberlink TrendMicroTrendMicro Umbo CVUmbo CV Google I/O ExtendGoogle I/O Extend Golang TaipeiGolang Taipei   
A high performance, open source, general purpose standards-based, feature-rich RPC framework.
O(10^10) RPCs per second at Google
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
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
gRPC: FeaturesgRPC: Features Bi-directional streaming over HTTP/2 Support multi-language, multi-platform Simple service definition framework
Bi-directional streaming over HTTP/2Bi-directional streaming over HTTP/2 Single TCP connection for each client-server pair Support bi-directional streaming
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
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
syntax = "proto3"; package pb; message EchoMessage { string msg = 1; } service EchoService { rpc Echo(EchoMessage) returns (EchoMessage); } Protobuf IDL: EchoServiceProtobuf IDL: EchoService
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
Example: DemoServiceExample: DemoService
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); }
gRPC Service DefinitiongRPC Service Definition gRPC supprots 4 kinds of service methods Unary RPC Server streaming RPC Client streaming RPC Bidirectional RPC
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
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 }
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) }
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) }
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) } }
Let's go deeperLet's go deeper
gRPC build-in authenticationgRPC build-in authentication Two types of Credentials objects Channel credentials Call credentials
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
Call credentialsCall credentials Credentials are attached to each RPC call Token based authentication, ex: OAuth, JWT
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
gRPC load balancegRPC load balance Approaches to Load Balancing Server-side LB Client-side LB
Load Balancing in gRPCLoad Balancing in gRPC #gRPC load balancing proposal
Any Question?Any Question?

Build microservice with gRPC in golang

  • 1.
    Build microserviceBuild microservice withgRPC in Golangwith gRPC in Golang David Chou
  • 2.
    We are UmboWeare Umbo Computer VisionComputer Vision We buildWe build autonomous videoautonomous video security systemsecurity system
  • 3.
    CyberlinkCyberlink TrendMicroTrendMicro Umbo CVUmbo CV GoogleI/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 persecond at Google
  • 6.
    gRPC: MotivationgRPC: Motivation Googlehas 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 Ahigh 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-directionalstreaming over HTTP/2 Support multi-language, multi-platform Simple service definition framework
  • 9.
    Bi-directional streaming overHTTP/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 Useprotoc 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 definitionframeworkSimple 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"; packagepb; message EchoMessage { string msg = 1; } service EchoService { rpc Echo(EchoMessage) returns (EchoMessage); } Protobuf IDL: EchoServiceProtobuf IDL: EchoService
  • 13.
    BenchmarkToJSON_1000_Director-2 500 2512808ns/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
  • 15.
  • 16.
    gRPC Service DefinitiongRPCService 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); }
  • 17.
    gRPC Service DefinitiongRPCService Definition gRPC supprots 4 kinds of service methods Unary RPC Server streaming RPC Client streaming RPC Bidirectional RPC
  • 18.
    Generate client andserver 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
  • 19.
    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 }
  • 20.
    Go ServerGo Server typeserver 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) }
  • 21.
    Go Client: SimpleRPCGoClient: 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) }
  • 22.
    Go Client: ServerStreamGoClient: 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) } }
  • 23.
  • 24.
    gRPC build-in authenticationgRPCbuild-in authentication Two types of Credentials objects Channel credentials Call credentials
  • 25.
    Channel credentialsChannel credentials Credentialsare 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
  • 26.
    Call credentialsCall credentials Credentialsare attached to each RPC call Token based authentication, ex: OAuth, JWT
  • 27.
    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
  • 28.
    gRPC load balancegRPCload balance Approaches to Load Balancing Server-side LB Client-side LB
  • 31.
    Load Balancing ingRPCLoad Balancing in gRPC #gRPC load balancing proposal
  • 32.