diff --git a/Documentation/server-reflection-tutorial.md b/Documentation/server-reflection-tutorial.md index 2e3d1c771..665720693 100644 --- a/Documentation/server-reflection-tutorial.md +++ b/Documentation/server-reflection-tutorial.md @@ -1,16 +1,19 @@ # gRPC Server Reflection Tutorial gRPC Server Reflection provides information about publicly-accessible gRPC -services on a server, and assists clients at runtime to construct RPC -requests and responses without precompiled service information. It is used by -gRPC CLI, which can be used to introspect server protos and send/receive test -RPCs. +services on a server, and assists clients at runtime to construct RPC requests +and responses without precompiled service information. It is used by gRPC CLI, +which can be used to introspect server protos and send/receive test RPCs. ## Enable Server Reflection -gRPC-go Server Reflection is implemented in package [reflection](https://github.com/grpc/grpc-go/tree/master/reflection). To enable server reflection, you need to import this package and register reflection service on your gRPC server. +gRPC-go Server Reflection is implemented in package +[reflection](https://github.com/grpc/grpc-go/tree/master/reflection). To enable +server reflection, you need to import this package and register reflection +service on your gRPC server. -For example, to enable server reflection in `example/helloworld`, we need to make the following changes: +For example, to enable server reflection in `example/helloworld`, we need to +make the following changes: ```diff --- a/examples/helloworld/greeter_server/main.go @@ -33,12 +36,15 @@ For example, to enable server reflection in `example/helloworld`, we need to mak } ``` -We have made this change in `example/helloworld`, and we will use it as an example to show the use of gRPC server reflection and gRPC CLI in this tutorial. +An example server with reflection registered can be found at +`examples/features/reflection/server`. ## gRPC CLI -After enabling Server Reflection in a server application, you can use gRPC CLI to check its services. -gRPC CLI is only available in c++. Instructions on how to use gRPC CLI can be found at [command_line_tool.md](https://github.com/grpc/grpc/blob/master/doc/command_line_tool.md). +After enabling Server Reflection in a server application, you can use gRPC CLI +to check its services. gRPC CLI is only available in c++. Instructions on how to +use gRPC CLI can be found at +[command_line_tool.md](https://github.com/grpc/grpc/blob/master/doc/command_line_tool.md). To build gRPC CLI: @@ -55,7 +61,7 @@ First, start the helloworld server in grpc-go directory: ```sh $ cd -$ go run examples/helloworld/greeter_server/main.go +$ go run examples/features/reflection/server/main.go ``` Open a new terminal and make sure you are in the directory where grpc_cli lives: @@ -76,8 +82,9 @@ $ cd /bins/opt output: ```sh - helloworld.Greeter + grpc.examples.echo.Echo grpc.reflection.v1alpha.ServerReflection + helloworld.Greeter ``` - List one service with details diff --git a/examples/features/reflection/README.md b/examples/features/reflection/README.md new file mode 100644 index 000000000..068ef64e0 --- /dev/null +++ b/examples/features/reflection/README.md @@ -0,0 +1,21 @@ +# Reflection + +This example shows how reflection can be registered on a gRPC server. + +See +https://github.com/grpc/grpc-go/blob/master/Documentation/server-reflection-tutorial.md +for a tutorial. + + +# Try it + +```go +go run server/main.go +``` + +There are multiple existing reflection clients. + +To use `gRPC CLI`, follow +https://github.com/grpc/grpc-go/blob/master/Documentation/server-reflection-tutorial.md#grpc-cli. + +To use `grpcurl`, see https://github.com/fullstorydev/grpcurl. diff --git a/examples/features/reflection/server/main.go b/examples/features/reflection/server/main.go new file mode 100644 index 000000000..c5630025d --- /dev/null +++ b/examples/features/reflection/server/main.go @@ -0,0 +1,87 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// Binary server is an example server. +package main + +import ( + "context" + "flag" + "fmt" + "log" + "net" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + ecpb "google.golang.org/grpc/examples/features/proto/echo" + hwpb "google.golang.org/grpc/examples/helloworld/helloworld" + "google.golang.org/grpc/reflection" + "google.golang.org/grpc/status" +) + +var port = flag.Int("port", 50051, "the port to serve on") + +// hwServer is used to implement helloworld.GreeterServer. +type hwServer struct{} + +// SayHello implements helloworld.GreeterServer +func (s *hwServer) SayHello(ctx context.Context, in *hwpb.HelloRequest) (*hwpb.HelloReply, error) { + return &hwpb.HelloReply{Message: "Hello " + in.Name}, nil +} + +type ecServer struct{} + +func (s *ecServer) UnaryEcho(ctx context.Context, req *ecpb.EchoRequest) (*ecpb.EchoResponse, error) { + return &ecpb.EchoResponse{Message: req.Message}, nil +} + +func (s *ecServer) ServerStreamingEcho(*ecpb.EchoRequest, ecpb.Echo_ServerStreamingEchoServer) error { + return status.Errorf(codes.Unimplemented, "not implemented") +} + +func (s *ecServer) ClientStreamingEcho(ecpb.Echo_ClientStreamingEchoServer) error { + return status.Errorf(codes.Unimplemented, "not implemented") +} + +func (s *ecServer) BidirectionalStreamingEcho(ecpb.Echo_BidirectionalStreamingEchoServer) error { + return status.Errorf(codes.Unimplemented, "not implemented") +} + +func main() { + flag.Parse() + lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port)) + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + fmt.Printf("server listening at %v\n", lis.Addr()) + + s := grpc.NewServer() + + // Register Greeter on the server. + hwpb.RegisterGreeterServer(s, &hwServer{}) + + // Register RouteGuide on the same server. + ecpb.RegisterEchoServer(s, &ecServer{}) + + // Register reflection service on gRPC server. + reflection.Register(s) + + if err := s.Serve(lis); err != nil { + log.Fatalf("failed to serve: %v", err) + } +} diff --git a/examples/helloworld/greeter_server/main.go b/examples/helloworld/greeter_server/main.go index d1c38f6ba..b339a6102 100644 --- a/examples/helloworld/greeter_server/main.go +++ b/examples/helloworld/greeter_server/main.go @@ -27,7 +27,6 @@ import ( "google.golang.org/grpc" pb "google.golang.org/grpc/examples/helloworld/helloworld" - "google.golang.org/grpc/reflection" ) const ( @@ -50,8 +49,6 @@ func main() { } s := grpc.NewServer() pb.RegisterGreeterServer(s, &server{}) - // Register reflection service on gRPC server. - reflection.Register(s) if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) }