| Eric Gribkoff | e08034c | 2017-01-30 12:57:48 -0800 | [diff] [blame] | 1 | # gRPC Server Reflection Tutorial |
| 2 | |
| 3 | gRPC Server Reflection provides information about publicly-accessible gRPC |
| 4 | services on a server, and assists clients at runtime with constructing RPC |
| 5 | requests and responses without precompiled service information. It is used by |
| 6 | the gRPC command line tool (gRPC CLI), which can be used to introspect server |
| 7 | protos and send/receive test RPCs. Reflection is only supported for |
| 8 | proto-based services. |
| 9 | |
| 10 | ## Enable Server Reflection |
| 11 | |
| 12 | gRPC-Java Server Reflection is implemented by |
| Eric Gribkoff | 00bebc4 | 2017-03-20 12:41:33 -0700 | [diff] [blame^] | 13 | `io.grpc.protobuf.services.ProtoReflectionService` in the `grpc-services` |
| Eric Gribkoff | e08034c | 2017-01-30 12:57:48 -0800 | [diff] [blame] | 14 | package. To enable server reflection, you need to add the |
| 15 | `ProtoReflectionService` to your gRPC server. |
| 16 | |
| 17 | For example, to enable server reflection in |
| 18 | `examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java`, we |
| 19 | need to make the following changes: |
| 20 | |
| 21 | ```diff |
| 22 | --- a/examples/build.gradle |
| 23 | +++ b/examples/build.gradle |
| Eric Anderson | a7b4dfd | 2017-02-01 10:20:44 -0800 | [diff] [blame] | 24 | @@ -27,6 +27,7 @@ |
| Eric Gribkoff | e08034c | 2017-01-30 12:57:48 -0800 | [diff] [blame] | 25 | dependencies { |
| 26 | compile "io.grpc:grpc-netty:${grpcVersion}" |
| 27 | compile "io.grpc:grpc-protobuf:${grpcVersion}" |
| 28 | + compile "io.grpc:grpc-services:${grpcVersion}" |
| 29 | compile "io.grpc:grpc-stub:${grpcVersion}" |
| Eric Gribkoff | 00bebc4 | 2017-03-20 12:41:33 -0700 | [diff] [blame^] | 30 | |
| Eric Gribkoff | e08034c | 2017-01-30 12:57:48 -0800 | [diff] [blame] | 31 | testCompile "junit:junit:4.11" |
| Eric Gribkoff | e08034c | 2017-01-30 12:57:48 -0800 | [diff] [blame] | 32 | --- a/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java |
| 33 | +++ b/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java |
| 34 | @@ -33,6 +33,7 @@ package io.grpc.examples.helloworld; |
| Eric Gribkoff | 00bebc4 | 2017-03-20 12:41:33 -0700 | [diff] [blame^] | 35 | |
| Eric Gribkoff | e08034c | 2017-01-30 12:57:48 -0800 | [diff] [blame] | 36 | import io.grpc.Server; |
| 37 | import io.grpc.ServerBuilder; |
| Eric Gribkoff | 00bebc4 | 2017-03-20 12:41:33 -0700 | [diff] [blame^] | 38 | +import io.grpc.protobuf.services.ProtoReflectionService; |
| Eric Gribkoff | e08034c | 2017-01-30 12:57:48 -0800 | [diff] [blame] | 39 | import io.grpc.stub.StreamObserver; |
| Eric Gribkoff | e08034c | 2017-01-30 12:57:48 -0800 | [diff] [blame] | 40 | import java.io.IOException; |
| Eric Gribkoff | 00bebc4 | 2017-03-20 12:41:33 -0700 | [diff] [blame^] | 41 | import java.util.logging.Logger; |
| 42 | @@ -50,6 +51,7 @@ public class HelloWorldServer { |
| Eric Gribkoff | e08034c | 2017-01-30 12:57:48 -0800 | [diff] [blame] | 43 | int port = 50051; |
| 44 | server = ServerBuilder.forPort(port) |
| 45 | .addService(new GreeterImpl()) |
| Eric Gribkoff | 00bebc4 | 2017-03-20 12:41:33 -0700 | [diff] [blame^] | 46 | + .addService(ProtoReflectionService.newInstance()) |
| Eric Gribkoff | e08034c | 2017-01-30 12:57:48 -0800 | [diff] [blame] | 47 | .build() |
| 48 | .start(); |
| 49 | logger.info("Server started, listening on " + port); |
| 50 | ``` |
| 51 | |
| 52 | In the following examples, we assume you have made these changes to |
| 53 | enable reflection in `HelloWorldServer.java`. |
| 54 | |
| 55 | ## gRPC CLI |
| 56 | |
| 57 | After enabling server reflection in a server application, you can use gRPC |
| 58 | CLI to get information about its available services. gRPC CLI is written |
| 59 | in C++. Instructions on how to build gRPC CLI can be found at |
| 60 | [command_line_tool.md](https://github.com/grpc/grpc/blob/master/doc/command_line_tool.md). |
| 61 | |
| 62 | ## Use gRPC CLI to check services |
| 63 | |
| 64 | First, build and start the `hello-world-server`: |
| 65 | |
| 66 | ```sh |
| 67 | $ cd examples/ |
| 68 | $ ./gradlew installDist |
| 69 | $ build/install/examples/bin/hello-world-server |
| 70 | ``` |
| 71 | |
| 72 | Open a new terminal and make sure you are in the directory where the `grpc_cli` |
| 73 | binary is located: |
| 74 | |
| 75 | ```sh |
| 76 | $ cd <grpc-cpp-directory>/bins/opt |
| 77 | ``` |
| 78 | |
| 79 | ### List services |
| 80 | |
| 81 | `grpc_cli ls` command lists services and methods exposed at a given port: |
| 82 | |
| 83 | - List all the services exposed at a given port |
| 84 | |
| 85 | ```sh |
| 86 | $ ./grpc_cli ls localhost:50051 |
| 87 | ``` |
| 88 | |
| 89 | output: |
| 90 | ```sh |
| 91 | helloworld.Greeter |
| 92 | grpc.reflection.v1alpha.ServerReflection |
| 93 | ``` |
| 94 | |
| 95 | - List one service with details |
| 96 | |
| 97 | `grpc_cli ls` command inspects a service given its full name (in the format of |
| 98 | \<package\>.\<service\>). It can print information with a long listing format |
| 99 | when `-l` flag is set. This flag can be used to get more details about a |
| 100 | service. |
| 101 | |
| 102 | ```sh |
| 103 | $ ./grpc_cli ls localhost:50051 helloworld.Greeter -l |
| 104 | ``` |
| 105 | |
| 106 | output: |
| 107 | ```sh |
| 108 | filename: helloworld.proto |
| 109 | package: helloworld; |
| 110 | service Greeter { |
| 111 | rpc SayHello(helloworld.HelloRequest) returns (helloworld.HelloReply) {} |
| 112 | } |
| 113 | |
| 114 | ``` |
| 115 | |
| 116 | ### List methods |
| 117 | |
| 118 | - List one method with details |
| 119 | |
| 120 | `grpc_cli ls` command also inspects a method given its full name (in the |
| 121 | format of \<package\>.\<service\>.\<method\>). |
| 122 | |
| 123 | ```sh |
| 124 | $ ./grpc_cli ls localhost:50051 helloworld.Greeter.SayHello -l |
| 125 | ``` |
| 126 | |
| 127 | output: |
| 128 | ```sh |
| 129 | rpc SayHello(helloworld.HelloRequest) returns (helloworld.HelloReply) {} |
| 130 | ``` |
| 131 | |
| 132 | ### Inspect message types |
| 133 | |
| 134 | We can use`grpc_cli type` command to inspect request/response types given the |
| 135 | full name of the type (in the format of \<package\>.\<type\>). |
| 136 | |
| 137 | - Get information about the request type |
| 138 | |
| 139 | ```sh |
| 140 | $ ./grpc_cli type localhost:50051 helloworld.HelloRequest |
| 141 | ``` |
| 142 | |
| 143 | output: |
| 144 | ```sh |
| 145 | message HelloRequest { |
| 146 | optional string name = 1[json_name = "name"]; |
| 147 | } |
| 148 | ``` |
| 149 | |
| 150 | ### Call a remote method |
| 151 | |
| 152 | We can send RPCs to a server and get responses using `grpc_cli call` command. |
| 153 | |
| 154 | - Call a unary method |
| 155 | |
| 156 | ```sh |
| 157 | $ ./grpc_cli call localhost:50051 SayHello "name: 'gRPC CLI'" |
| 158 | ``` |
| 159 | |
| 160 | output: |
| 161 | ```sh |
| 162 | message: "Hello gRPC CLI" |
| 163 | ``` |