Skip to content

Commit efce51b

Browse files
authored
examples: add reflection example (#9955)
1 parent dc313f2 commit efce51b

File tree

5 files changed

+279
-0
lines changed

5 files changed

+279
-0
lines changed

examples/example-reflection/README.md

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
gRPC Reflection Example
2+
================
3+
4+
The reflection example has a Hello World server with `ProtoReflectionService` registered.
5+
6+
### Build the example
7+
8+
To build the example server, from the `grpc-java/examples/examples-reflection`
9+
directory:
10+
```
11+
$ ../gradlew installDist
12+
```
13+
14+
This creates the scripts `build/install/example-reflection/bin/reflection-server`.
15+
16+
### Run the example
17+
18+
gRPC Server Reflection provides information about publicly-accessible gRPC services on a server,
19+
and assists clients at runtime to construct RPC requests and responses without precompiled
20+
service information. It is used by gRPCurl, which can be used to introspect server protos and
21+
send/receive test RPCs.
22+
23+
1. To start the reflection example server on its default port of 50051, run:
24+
```
25+
$ ./build/install/example-reflection/bin/reflection-server
26+
```
27+
28+
2. After enabling Server Reflection in a server application, you can use gRPCurl to check its
29+
services. Instructions on how to install and use gRPCurl can be found at [gRPCurl Installation](https://github.com/fullstorydev/grpcurl#installation)
30+
31+
After installing gRPCurl, open a new terminal and run the commands from the new terminal.
32+
33+
### List all the services exposed at a given port
34+
35+
```
36+
$ grpcurl -plaintext localhost:50051 list
37+
```
38+
39+
Output
40+
41+
```
42+
grpc.reflection.v1alpha.ServerReflection
43+
helloworld.Greeter
44+
```
45+
46+
### List all the methods of a service
47+
```
48+
$ grpcurl -plaintext localhost:50051 helloworld.Greeter
49+
```
50+
Output
51+
```
52+
helloworld.Greeter.SayHello
53+
```
54+
55+
### Describe services and methods
56+
57+
The describe command inspects a method given its full name(in the format of
58+
`<package>.<service>.<method>`).
59+
60+
```
61+
$ grpcurl -plaintext localhost:50051 describe helloworld.Greeter.SayHello
62+
```
63+
64+
Output
65+
66+
```
67+
helloworld.Greeter.SayHello is a method:
68+
rpc SayHello ( .helloworld.HelloRequest ) returns ( .helloworld.HelloReply );
69+
```
70+
71+
### Inspect message types
72+
73+
We can use the describe command to inspect request/response types given the full name of the type
74+
(in the format of `<package>.<type>`).
75+
76+
Get information about the request type:
77+
78+
```
79+
$ grpcurl -plaintext localhost:50051 describe helloworld.HelloRequest
80+
```
81+
82+
Output
83+
84+
```
85+
helloworld.HelloRequest is a message:
86+
message HelloRequest {
87+
string name = 1;
88+
}
89+
```
90+
91+
### Call a remote method
92+
93+
We can send RPCs to a server and get responses using the full method name
94+
(in the format of `<package>.<service>.<method>`). The `-d <string>` flag represents the request data
95+
and the -format text flag indicates that the request data is in text format.
96+
97+
```
98+
$ grpcurl -plaintext -format text -d 'name: "gRPCurl"' \
99+
localhost:50051 helloworld.Greeter.SayHello
100+
```
101+
102+
Output
103+
104+
```
105+
message: "Hello gRPCurl"
106+
```
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
plugins {
2+
id 'application' // Provide convenience executables for trying out the examples.
3+
// ASSUMES GRADLE 5.6 OR HIGHER. Use plugin version 0.8.10 with earlier gradle versions
4+
id 'com.google.protobuf' version '0.8.17'
5+
// Generate IntelliJ IDEA's .idea & .iml project files
6+
id 'idea'
7+
id 'java'
8+
}
9+
10+
repositories {
11+
maven { // The google mirror is less flaky than mavenCentral()
12+
url "https://maven-central.storage-download.googleapis.com/maven2/" }
13+
mavenCentral()
14+
mavenLocal()
15+
}
16+
17+
sourceCompatibility = 1.8
18+
targetCompatibility = 1.8
19+
20+
def grpcVersion = '1.55.0-SNAPSHOT' // CURRENT_GRPC_VERSION
21+
def protocVersion = '3.21.7'
22+
23+
dependencies {
24+
implementation "io.grpc:grpc-protobuf:${grpcVersion}"
25+
implementation "io.grpc:grpc-services:${grpcVersion}"
26+
implementation "io.grpc:grpc-stub:${grpcVersion}"
27+
implementation "io.grpc:grpc-netty-shaded:${grpcVersion}"
28+
compileOnly "org.apache.tomcat:annotations-api:6.0.53"
29+
30+
}
31+
32+
protobuf {
33+
protoc { artifact = "com.google.protobuf:protoc:${protocVersion}" }
34+
plugins {
35+
grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" }
36+
}
37+
generateProtoTasks {
38+
all()*.plugins { grpc {} }
39+
}
40+
}
41+
42+
startScripts.enabled = false
43+
44+
task ReflectionServer(type: CreateStartScripts) {
45+
mainClass = 'io.grpc.examples.reflection.ReflectionServer'
46+
applicationName = 'reflection-server'
47+
outputDir = new File(project.buildDir, 'tmp/scripts/' + name)
48+
classpath = startScripts.classpath
49+
}
50+
51+
applicationDistribution.into('bin') {
52+
from(ReflectionServer)
53+
fileMode = 0755
54+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rootProject.name = 'example-reflection'
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
2+
package io.grpc.examples.reflection;
3+
4+
import io.grpc.Grpc;
5+
import io.grpc.InsecureServerCredentials;
6+
import io.grpc.Server;
7+
import io.grpc.examples.helloworld.GreeterGrpc;
8+
import io.grpc.examples.helloworld.HelloReply;
9+
import io.grpc.examples.helloworld.HelloRequest;
10+
import io.grpc.protobuf.services.ProtoReflectionService;
11+
import io.grpc.stub.StreamObserver;
12+
import java.io.IOException;
13+
import java.util.concurrent.TimeUnit;
14+
import java.util.logging.Logger;
15+
16+
/**
17+
* Server that manages startup/shutdown of a {@code Greeter} server.
18+
*/
19+
public class ReflectionServer {
20+
private static final Logger logger = Logger.getLogger(ReflectionServer.class.getName());
21+
22+
private Server server;
23+
24+
private void start() throws IOException {
25+
/* The port on which the server should run */
26+
int port = 50051;
27+
server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
28+
.addService(new GreeterImpl())
29+
.addService(ProtoReflectionService.newInstance()) // add reflection service
30+
.build()
31+
.start();
32+
logger.info("Server started, listening on " + port);
33+
Runtime.getRuntime().addShutdownHook(new Thread() {
34+
@Override
35+
public void run() {
36+
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
37+
System.err.println("*** shutting down gRPC server since JVM is shutting down");
38+
try {
39+
ReflectionServer.this.stop();
40+
} catch (InterruptedException e) {
41+
e.printStackTrace(System.err);
42+
}
43+
System.err.println("*** server shut down");
44+
}
45+
});
46+
}
47+
48+
private void stop() throws InterruptedException {
49+
if (server != null) {
50+
server.shutdown().awaitTermination(30, TimeUnit.SECONDS);
51+
}
52+
}
53+
54+
/**
55+
* Await termination on the main thread since the grpc library uses daemon threads.
56+
*/
57+
private void blockUntilShutdown() throws InterruptedException {
58+
if (server != null) {
59+
server.awaitTermination();
60+
}
61+
}
62+
63+
/**
64+
* Main launches the server from the command line.
65+
*/
66+
public static void main(String[] args) throws IOException, InterruptedException {
67+
final ReflectionServer server = new ReflectionServer();
68+
server.start();
69+
server.blockUntilShutdown();
70+
}
71+
72+
static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
73+
74+
@Override
75+
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
76+
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
77+
responseObserver.onNext(reply);
78+
responseObserver.onCompleted();
79+
}
80+
}
81+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2022 The gRPC Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
syntax = "proto3";
15+
16+
option java_multiple_files = true;
17+
option java_package = "io.grpc.examples.helloworld";
18+
option java_outer_classname = "HelloWorldProto";
19+
option objc_class_prefix = "HLW";
20+
21+
package helloworld;
22+
23+
// The greeting service definition.
24+
service Greeter {
25+
// Sends a greeting
26+
rpc SayHello (HelloRequest) returns (HelloReply) {}
27+
}
28+
29+
// The request message containing the user's name.
30+
message HelloRequest {
31+
string name = 1;
32+
}
33+
34+
// The response message containing the greetings
35+
message HelloReply {
36+
string message = 1;
37+
}

0 commit comments

Comments
 (0)