The gRPC framework leverages the stream multiplexing capabilities of HTTP/2 so that it can handle both synchronous and asynchronous RPCs. The protoc compiler, when invoked with the grpc plugin enabled, will generate the following:
- Client and server interfaces for every RPC service definition in the compiled .proto file. For a service named Foo, the compiler will generate a FooServer and a FooClient interface. This is quite a useful feature as it allows us to inject mocked clients into our code at test time.
- Complete client implementation for each service that adheres to the generated client interface.
- A helper function to register our service implementation with a gRPC server instance. Once again, for a service called Foo, the compiler will generate a function with a signature similar to RegisterFooServer(*grpc.Server, FooServer).
The following short code snippet demonstrates how we can create a new gRPC server, register our implementation for the Foo service, and start serving incoming RPCs:
func serve(addr string, serverImpl FooServer) error {
l, err := net.Listen("tcp", addr)
if err != nil {
return err
}
grpcServer := grpc.NewServer()
RegisterFooServer(grpcServer, serverImpl)
return grpcServer.Serve(l)
}
In the following four sections, we will examine the different types of RPC modes that are supported by the gRPC framework.