aboutsummaryrefslogtreecommitdiffhomepage
path: root/doc/server_reflection_tutorial.md
blob: 06a257c1e87dacc8c7d7785cd5c4f6ccfa9b64f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# 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.

## Enable Server Reflection

### Enable server reflection in C++ servers

C++ Server Reflection is an add-on library, `libgrpc++_reflection`. To enable C++
server reflection, you can link this library to your server binary.

Some platforms (e.g. Ubuntu 11.10 onwards) only link in libraries that directly
contain symbols used by the application. On these platforms, LD flag
`--no-as-needed` is needed for for dynamic linking and `--whole-archive` is
needed for for static linking.

This [Makefile](../examples/cpp/helloworld/Makefile#L37#L45) demonstrates
enabling c++ server reflection on Linux and MacOS.

## Test services using Server Reflection

After enabling Server Reflection in a server application, you can use gRPC CLI
to test its services.

Instructions on how to use gRPC CLI can be found at
[command_line_tool.md](command_line_tool.md), or using `grpc_cli help` command.

Here we use `examples/cpp/helloworld` as an example to show the use of gRPC
Server Reflection and gRPC CLI. First, we need to build gRPC CLI and setup an
example server with Server Reflection enabled.

- Setup an example server

  Server Reflection has already been enabled in the
  [Makefile](../examples/cpp/helloworld/Makefile) of the helloworld example. We
  can simply make it and run the greeter_server.

  ```sh
  $ make -C examples/cpp/helloworld
  $ examples/cpp/helloworld/greeter_server &
  ```

- Build gRPC CLI

  ```sh
  make grpc_cli
  cd bins/opt
  ```

  gRPC CLI binary `grpc_cli` can be found at `bins/opt/` folder. This tool is
  still new and does not have a `make install` target yet.

### List services

`grpc_cli ls` command lists services and methods exposed at a given port

- List all the services exposed at a given port

  ```sh
  $ grpc_cli ls localhost:50051
  ```

  output:
  ```sh
  helloworld.Greeter
  grpc.reflection.v1alpha.ServerReflection
  ```

- List one service with details

  `grpc_cli ls` command inspects a service given its full name (in the format of
  \<package\>.\<service\>). It can print information with a long listing format
  when `-l` flag is set. This flag can be used to get more details about a
  service.

  ```sh
  $ grpc_cli ls localhost:50051 helloworld.Greeter -l
  ```

  output:
  ```sh
  filename: helloworld.proto
  package: helloworld;
  service Greeter {
    rpc SayHello(helloworld.HelloRequest) returns (helloworld.HelloReply) {}
  }

  ```

### List methods

- List one method with details

  `grpc_cli ls` command also inspects a method given its full name (in the
  format of \<package\>.\<service\>.\<method\>).

  ```sh
  $ grpc_cli ls localhost:50051 helloworld.Greeter.SayHello -l
  ```

  output:
  ```sh
    rpc SayHello(helloworld.HelloRequest) returns (helloworld.HelloReply) {}
  ```

### Inspect message types

We can use`grpc_cli type` command to inspect request/response types given the
full name of the type (in the format of \<package\>.\<type\>).

- Get information about the request type

  ```sh
  $ grpc_cli type localhost:50051 helloworld.HelloRequest
  ```

  output:
  ```sh
  message HelloRequest {
    optional string name = 1;
  }
  ```

### Call a remote method

We can send RPCs to a server and get responses using `grpc_cli call` command.

- Call a unary method

  ```sh
  $ grpc_cli call localhost:50051 SayHello "name: 'gRPC CLI'"
  ```

  output:
  ```sh
  message: "Hello gRPC CLI"
  ```

## Use Server Reflection in a C++ client

Server Reflection can be used by clients to get information about gRPC services
at runtime. We've provided a descriptor database called
[grpc::ProtoReflectionDescriptorDatabase](../test/cpp/util/proto_reflection_descriptor_database.h)
which implements the
[google::protobuf::DescriptorDatabase](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.descriptor_database#DescriptorDatabase)
interface. It manages the communication between clients and reflection services
and the storage of received information. Clients can use it as using a local
descriptor database.

- To use Server Reflection with grpc::ProtoReflectionDescriptorDatabase, first
  initialize an instance with a grpc::Channel.

  ```c++
  std::shared_ptr<grpc::Channel> channel =
      grpc::CreateChannel(server_address, server_cred);
  grpc::ProtoReflectionDescriptorDatabase reflection_db(channel);
  ```

- Then use this instance to feed a
  [google::protobuf::DescriptorPool](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.descriptor#DescriptorPool).

  ```c++
  google::protobuf::DescriptorPool desc_pool(&reflection_db);
  ```

- Example usage of this descriptor pool

  * Get Service/method descriptors.

    ```c++
    const google::protobuf::ServiceDescriptor* service_desc =
        desc_pool->FindServiceByName("helloworld.Greeter");
    const google::protobuf::MethodDescriptor* method_desc =
        desc_pool->FindMethodByName("helloworld.Greeter.SayHello");
    ```

  * Get message type descriptors.

    ```c++
    const google::protobuf::Descriptor* request_desc =
        desc_pool->FindMessageTypeByName("helloworld.HelloRequest");
    ```

  * Feed [google::protobuf::DynamicMessageFactory](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.dynamic_message#DynamicMessageFactory).

    ```c++
    google::protobuf::DynamicMessageFactory(&desc_pool);
    ```